Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ dynamic class ( dynamic hack )

Tags:

c++

dynamic

Is there any way to add a field to a class at runtime ( a field that didn't exist before ) ? Something like this snippet :

Myobject *ob; // create an object
ob->addField("newField",44); // we add the field to the class and we assign an initial value to it
printf("%d",ob->newField); // now we can access that field

I don't really care how it would be done , I don't care if it's an ugly hack or not , I would like to know if it could be done , and a small example , if possible .

Another Example: say I have an XML file describing this class :

<class name="MyClass">
   <member name="field1" />
   <member name="field2" />
</class>

and I want to "add" the fields "field1" and "field2" to the class (assuming the class already exists) . Let's say this is the code for the class :

class MyClass {
};

I don't want to create a class at runtime , I just want to add members/fields to an existing one .

Thank you !

like image 792
Vhaerun Avatar asked Oct 24 '08 21:10

Vhaerun


3 Answers

Use a map and a variant.

For example, using boost::variant. See http://www.boost.org/doc/libs/1_36_0/doc/html/variant.html

(But of course, you can create your own, to suit the types of your XML attributes.)

#include <map>
#include <boost/variant.hpp>

typedef boost::variant< int, std::string > MyValue ;
typedef std::map<std::string, MyValue> MyValueMap ;

By adding MyValueMap as a member of your class, you can add properties according to their names. Which means the code:

oMyValueMap.insert(std::make_pair("newField", 44)) ;
oMyValueMap.insert(std::make_pair("newField2", "Hello World")) ;
std::cout << oMyValueMap["newField"] ;
std::cout << oMyValueMap["newField2"] ;

By encapsulating it in a MyObject class, and adding the right overloaded accessors in this MyObject class, the code above becomes somewhat clearer:

oMyObject.addField("newField", 44) ;
oMyObject.addField("newField2", "Hello World") ;
std::cout << oMyObject["newField"] ;
std::cout << oMyObject["newField2"] ;

But you lose somewhat the type safety of C++ doing so. But for XML, this is unavoidable, I guess.

like image 78
paercebal Avatar answered Oct 03 '22 11:10

paercebal


There's no way to do it in the way you've described, since the compiler needs to resolve the reference at compile time - it will generate an error.

But see The Universal Design Pattern.

like image 21
Mark Ransom Avatar answered Oct 03 '22 10:10

Mark Ransom


You can't make that syntax work (because of static checking at compile time), but if you're willing to modify the syntax, you can achieve the same effect pretty easily. It would be fairly easy to have a dictionary member with a string->blob mapping, and have member functions like:

template< typename T > T get_member( string name );
template< typename T > void set_member( string name, T value );

You could make the syntax more compact/tricky if you want (eg: using a '->' operator override). There are also some compiler-specific tricks you could possibly leverage (MSVC supports __declspec(property), for example, which allows you to map references to a member variable to methods of a specific format). At the end of the day, though, you're not going to be able to do something the compiler doesn't accept in the language and get it to compile.

like image 31
Nick Avatar answered Oct 03 '22 12:10

Nick