40

我正在努力在 C++ 中实现反射机制。我的代码中的所有对象都是 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 的任何子类,我希望能够使用指向该子类的构造函数的指针来初始化“create”。

4

7 回答 7

68

您不能获取构造函数的地址(C++98 标准 12.1/12 构造函数 - “12.1-12 构造函数 - “不应获取构造函数的地址。”)

你最好的选择是有一个工厂函数/方法来创建Object并传递工厂的地址:

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;
}
于 2009-06-05T06:55:15.870 回答
8

我遇到了同样的问题。我的解决方案是调用构造函数的模板函数。

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

将其用作函数指针很简单:

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

并获取 MyClass 的实例:

MyClass* myClass = createMyClass();
于 2017-05-26T01:27:04.640 回答
6

拉姆达风格:

[](){return new YourClass();}
于 2016-12-11T04:57:38.160 回答
3

嗯,奇怪。create是一个成员变量,即仅在类实例中可用,但它的意图似乎是首先创建一个实例。

您不能获取构造函数的地址,但您可以创建自己的静态工厂方法并获取该地址。

于 2009-06-05T06:56:58.380 回答
1

您不能在方法上使用常规函数指针,您必须使用具有奇怪语法的方法指针:

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);

当然,此时应该很明显,您不能使用方法指针指向对象构造函数。为了使用方法指针,你需要有一个类的实例,所以它的构造函数已经被调用了!所以在你的情况下,迈克尔的对象工厂建议可能是最好的方法。

于 2009-06-05T17:02:46.007 回答
0

使用可变参数模板,您可以创建一个包装器,它将构造函数转换为函子。

#include <utility>

template <typename T>
struct BindConstructor{
    template<typename... Args>
    T operator()(Args&&...args)const{
        return T(std::forward<Args>(args)...);
    }
};


struct Foo {
    Foo(int a, int b):a(a),b(b){}
    int a;
    int b;
};

template <typename Fn>
auto Bar(Fn f){
    return f(10,20);
}

int main(){
    Foo foo = Bar(BindConstructor<Foo>());
}

https://godbolt.org/z/5W383McTc

于 2020-06-16T15:49:43.873 回答
-1

使用 Qt,如果您将构造函数声明为 Q_INVOKABLE(仅此而已),则可以使用 Qt 反射机制 (QMetaObject) 调用构造函数。

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

于 2015-09-03T22:22:08.787 回答