views:

844

answers:

3

I'm working on implementing a reflection mechanism in C++. All objects within my code are a subclass of Object(my own generic type) that contain a static member datum of type 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
};

For any subclass of Object with a static Class member datum, I want to be able to initialize 'create' with a pointer to the constructor of that subclass.

+17  A: 

You cannot take the address of a constructor (C++98 Standard 12.1/12 Constructors - "12.1-12 Constructors - "The address of a constructor shall not be taken.")

Your best bet is to have a factory function/method that creates the Object and pass the address of the 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;
}
Michael Burr
sounds good,thanks Michael
Kareem
Making it a template will make it actually return "Class": template<typename T> Object* ObjectFactory() { return new T; } .... Class foo("myFoo",
Johannes Schaub - litb
+1  A: 

Hmm, odd. create is a member variable i.e. only available in class instances but the intent of it seems to be creating an instance in the first place.

You cannot take the address of a constructor, but you can create static factory methods of your own and take the address of that.

laalto
laalto,When I construct the Class object I pass in a name and a creation function. My goal is to have a list of Classes to which I can refer to anywhere in my project. A pointer to a static member function would work.
Kareem
A: 

You can't use regular function pointers on methods, you have to use method pointers, which have bizarre syntax:

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

This gives you a method pointer to MyClass's method - MyMethod. However this isn't a true pointer in that it's not an absolute memory address, it's basically an offset (more complicated than that due to virtual inheritance, but that stuff is implementation specific) into a class. So to use the method pointer, you have to supply it with a class, like this:

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

or

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

Of course it should be obvious at this point that you can't use a method pointer to point to an objects constructor. In order to use a method pointer you need to have an instance of the class so it's constructor has already been called! So in your case Michael's Object Factory suggestion is probably the best way of doing it.

Niki Yoshiuchi
Rob K
I have to add that there is more magic involved in getting the location of the code to call if the method is virtual, but the existence of the methods in no way depends on the existence of any instance of the class.
Rob K
Ah, so you are right. Conceptually it makes little difference to the OP, either way a method pointer won't work unless an instance of the class exists.I have fixed my post to reflect this.
Niki Yoshiuchi