我正在用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
};
对于具有静态Class成员数据的Object的任何子类,我希望能够使用指向该子类的构造函数的指针初始化“create”。
答案 0 :(得分:57)
您不能获取构造函数的地址(C ++ 98 Standard 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;
}
答案 1 :(得分:3)
我遇到了同样的问题。我的解决方案是一个模板函数,它调用了构造函数。
template<class T> MyClass* create()
{
return new T;
}
将此作为函数指针使用很简单:
MyClass* (*createMyClass)(void) = create<MyClass>;
获取MyClass的实例:
MyClass* myClass = createMyClass();
答案 2 :(得分:2)
create
是一个成员变量,即只在类实例中可用,但它的意图似乎是首先创建一个实例。
您不能获取构造函数的地址,但您可以创建自己的静态工厂方法并获取其地址。
答案 3 :(得分:2)
Lambda风格:
[](){return new YourClass();}
答案 4 :(得分: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);
当然,此时应该很明显,您不能使用方法指针指向对象构造函数。为了使用方法指针,你需要有一个类的实例,所以它的构造函数已被调用!因此,在您的情况下,Michael的Object Factory建议可能是最好的方法。
答案 5 :(得分: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>());
}
答案 6 :(得分:-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 ;-)但是也许你想看看它的做法。