Подтвердить что ты не робот

Как передать указатель функции, указывающий на конструктор?

Я работаю над реализацией механизма отражения в С++. Все объекты в моем коде являются подклассом Object (мой собственный общий тип), который содержит статическую членную дату типа Class.

class Class{
public:
   Class(const std::string &n, Object *(*c)());
protected:
   std::string name;     // Name for subclass
   Object *(*create)();  // Pointer to creation function for subclass
};

Для любого подкласса Object со статическим членом класса static я хочу иметь возможность инициализировать "create" с указателем на конструктор этого подкласса.

4b9b3361

Ответ 1

Вы не можете взять адрес конструктора (С++ 98 Standard 12.1/12 Constructors - "12.1-12 Конструкторы -" Адрес конструктора не должен быть выполнен ".)

Лучше всего иметь функцию/метод factory, который создает Object и передает адрес factory:

class Object;

class Class{
public:
   Class(const std::string &n, Object *(*c)()) : name(n), create(c) {};
protected:
   std::string name;     // Name for subclass
   Object *(*create)();  // Pointer to creation function for subclass
};

class Object {};

Object* ObjectFactory()
{
    return new Object;
}



int main(int argc, char**argv)
{
    Class foo( "myFoo", ObjectFactory);

    return 0;
}

Ответ 2

Хмм, странно. create - это переменная-член, доступная только в экземплярах класса, но цель состоит в том, чтобы создать экземпляр в первую очередь.

Вы не можете взять адрес конструктора, но вы можете создать собственные статические методы factory и принять адрес этого.

Ответ 3

Лямбда стиль:

[](){return new YourClass();}

Ответ 4

Вы не можете использовать обычные указатели на методы, вам нужно использовать указатели на методы, которые имеют странный синтаксис:

void (MyClass::*method_ptr)(int x, int y);
method_ptr = &MyClass::MyMethod;

Это дает вам указатель на метод MyClass - MyMethod. Однако это не истинный указатель на то, что он не является абсолютным адресом памяти, это в основном смещение (более сложное, чем это связано с виртуальным наследованием, но этот материал является специфичным для реализации) в класс. Поэтому, чтобы использовать указатель метода, вы должны предоставить его классу, например:

MyClass myclass;
myclass.*method_ptr(x, y);

или

MyClass *myclass = new MyClass;
myclass->*method_ptr(x, y);

Конечно, в этот момент должно быть очевидно, что вы не можете использовать указатель метода для указания на конструктор объектов. Чтобы использовать указатель метода, вам нужно иметь экземпляр класса, чтобы он уже был вызван конструктором! Поэтому в вашем случае предложение Michael Object Factory, вероятно, лучший способ сделать это.

Ответ 5

Используя Qt, вы можете вызвать конструктор с механизмами отражения Qt (QMetaObject), если вы объявите конструктор как Q_INVOKABLE (не более того, чтобы сделать это).

class MyClass : public QObject {
   Q_OBJECT
public:
   Q_INVOKABLE MyClass(int foo);
   MyClass *cloningMySelf() {
     return metaObject()->newInstance(Q_ARG(int, 42));
   }
};

Я не уверен, что вы захотите встраивать Qt только для этой функции;-), но, возможно, вам хотелось бы посмотреть, как он это делает.

http://doc.qt.io/qt-5/metaobjects.html#meta-object-system

Ответ 6

Я столкнулся с этой же проблемой. Моим решением была функция шаблона, которая называлась конструктором.

template<class T> MyClass* create()
{
    return new T;
}

Чтобы использовать это как функцию, указатель прост:

MyClass* (*createMyClass)(void) = create<MyClass>;

И чтобы получить экземпляр MyClass:

MyClass* myClass = createMyClass();