如何创建一个对象创建函数,该函数将由与其关联的名称调用?

威兹格

我有一个类继承层次结构:图->圆,点,线,矩形。

我需要创建一个函数,根据给定的层次结构,通过与其关联的名称来创建Circle图形对象。该函数应将unique_ptr返回给该对象。函数的参数是对象的名称及其特征(x,y,半径)。将新类添加到层次结构时,不应更改该功能。

告诉我,如何实现此功能?我不明白

例如 ??

unique_ptr<Figure> CreateFigure(const std::string& name) {
     if (name == "circle")
        return make_unique<Circle>();
     if (name == "line")
        return make_unique<Line>()
阿明·蒙蒂尼(Armin Montigny)

解决问题的标准方法是使用抽象工厂设计模式。

基于“密钥”。如名称(例如“ Circle”)或id(如整数“ 3”),将创建所需的类。

因此,工厂始终具有“创建”方法,并且容器存储所有“创建”方法。要存储所有方法,我们经常使用std::map

问题始终是,类层次结构中使用的构造函数可能具有不同数量的参数。不幸的是,这并不是那么容易实现,因为工厂“想”存储具有相同签名的功能。但这当然可以通过可变参数模板解决。

请参阅下面的解决方案:

#include <iostream>
#include <map>
#include <utility>
#include <any>


// Some demo classes ----------------------------------------------------------------------------------
struct Base {
    Base(int d) : data(d) {};
    virtual ~Base() { std::cout << "Destructor Base\n"; }
    virtual void print() { std::cout << "Print Base\n"; }
    int data{};
};
struct Child1 : public Base {
    Child1(int d, std::string s) : Base(d) { std::cout << "Constructor Child1 " << d << " " << s << "\n"; }
    virtual ~Child1() { std::cout << "Destructor Child1\n"; }
    virtual void print() { std::cout << "Print Child1: " << data << "\n"; }
};
struct Child2 : public Base {
    Child2(int d, char c, long l) : Base(d) { std::cout << "Constructor Child2 " << d << " " << c << " " << l << "\n"; }
    virtual ~Child2() { std::cout << "Destructor Child2\n"; }
    virtual void print() { std::cout << "Print Child2: " << data << "\n"; }
};
struct Child3 : public Base {
    Child3(int d, long l, char c, std::string s) : Base(d) { std::cout << "Constructor Child3 " << d << " " << l << " " << c << " " << s << "\n"; }
    virtual ~Child3() { std::cout << "Destructor Child3\n"; }
    virtual void print() { std::cout << "Print Child3: " << data << "\n"; }
};



using UPTRB = std::unique_ptr<Base>;


template <class Child, typename ...Args>
UPTRB createClass(Args...args) { return std::make_unique<Child>(args...); }

// The Factory ----------------------------------------------------------------------------------------
template <class Key, class Object>
class Factory
{
    std::map<Key, std::any> selector;
public:
    Factory() : selector() {}
    Factory(std::initializer_list<std::pair<const Key, std::any>> il) : selector(il) {}

    template<typename Function>
    void add(Key key, Function&& someFunction) { selector[key] = std::any(someFunction); };

    template <typename ... Args>
    Object create(Key key, Args ... args) {
        if (selector.find(key) != selector.end()) {
            return std::any_cast<std::add_pointer_t<Object(Args ...)>>(selector[key])(args...);
        }
        else return nullptr;
    }
};

int main()
{
    Factory<int, UPTRB> factory{
        {1, createClass<Child1, int, std::string>},
        {2, createClass<Child2, int, char, long>}
    };
    factory.add(3, createClass<Child3, int, long, char, std::string>);


    // Some test values
    std::string s1(" Hello1 "); std::string s3(" Hello3 ");
    int i = 1;  const int ci = 1;   int& ri = i;    const int& cri = i;   int&& rri = 1;

    UPTRB b1 = factory.create(1, 1, s1);
    UPTRB b2 = factory.create(2, 2, '2', 2L);
    UPTRB b3 = factory.create(3, 3, 3L, '3', s3);

    b1->print();
    b2->print();
    b3->print();
    b1 = factory.create(2, 4, '4', 4L);
    b1->print();
    return 0;
}

这里的一般创建功能是:

template <class Child, typename ...Args>
UPTRB createClass(Args...args) { return std::make_unique<Child>(args...); }

然后是存储所有创建功能的工厂。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

如何创建一个对象,该对象的对象在构造函数中可以执行该函数?

我可以创建一个函数,该函数是对象中函数的属性吗?

用茉莉花创建单元测试,并在第二次调用时得到一个对象。如何正确调用该函数?

创建一个聚合函数,该函数返回与最大column2值关联的column1值

如何在Swift中创建一个函数,该函数返回符合协议的Type?

Javascript对象。如何创建一个在同一对象内调用函数的按钮

如何创建调用某个函数时调用该函数的函数?

如何编写一个函数,该函数创建一定长度的对象数组?对象具有自定义生成的数据

如何创建一个函数,该函数生成一个空向量,然后使用for循环的结果填充它?

如何使用 zipWithIndex 创建一个函数,该函数从 Scala 中的 List[Int] 返回一个 Int

创建一个循环来调用php函数,并在javascript的同一html页面上从该函数回显

创建一个函数,该函数接受具有相同方法的两个不同对象

如何创建一个包含函数名称的列表?

如何创建一个可以在javascript中的对象上调用的函数

我如何在ASP.NET中创建一个回调函数,当引发数据库事件时调用该函数?

根据现有函数中的一个免费参数创建一个可调用函数,该函数在python中具有许多参数

从另一个函数中调用python中的函数(为该函数的变量创建一个数组)

如何创建一个值是函数的对象?

一个函数,该函数创建可以被查询次数的函数

一个函数,该函数创建以传入的参数命名的函数

创建一个 get 函数,该函数在使用 getchar 函数按下时返回 char*

Python函数如何使用该函数的参数中定义的名称创建全局对象?

我有一种从String []中删除空值的方法,我该如何为该函数创建一个方法并稍后对其进行调用?爪哇

如何在c ++中创建一个函数,该函数具有由参数确定的矩阵大小?

使用泛型创建一个函数,该函数将在Swift中返回另一个函数

UML类图:如果该函数返回一个函数调用,该函数的返回类型将如何处理?

当从另一个函数中调用该函数时,如何抑制该函数中的代码行?

是否可以创建一个返回创建时生成的静态值的函数,而不是调用该函数时返回的静态值?

创建一个C ++模板函数,该函数将返回特定大小的std :: array