Jump to content
  • Advertisement
Sign in to follow this  
irreversible

member type names for inherited classes (the issue is a tad more complex)

This topic is 4869 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

What I want to do is to automatically map all member variables of a class in a dynamic lookup table to create a generic runtime access interfaces for them. For instance:
#define registerProperty(ref, desc) /
__doAddProperty((char*)typeid(this).name(), (int*)&ref, (void*)this, (char*)typeid(ref).name(), sizeof(ref), desc);

class Car {
 private:
  int type;

 public:
  Car() {
  registerProperty(type, "The type of the car");
  } 
};
would call a function called __doAddProperty(), which creates an interface for the class Car that stores all instances of the class, plus descriptions for all the member variables in it. Additionally, each time the constructor for Car gets called, an instance is added to the generic interface class that provides referencial access to all of the member variables, which can then be modified or read without actually having to know the inner workings of the class. This works out quite nicely - to an extent. All that is required is a notification in the destructor of the base class that would remove the instance from the generic interface class once it is destroyed. The problem comes with inheritance.
#define registerProperty(ref, desc) /
__doAddProperty((char*)typeid(this).name(), (int*)&ref, (void*)this, (char*)typeid(ref).name(), sizeof(ref), desc);

class Car {
 private:
  int type;
  float length;

 public:
  Car() {
  registerProperty(type, "The type of the car");
  registerProperty(length, "The length of the car");
  } 
};


class FordEscort : public Car {
 private:
  COLORREF color_of_fancy_dashboard;

 public:
  FordEscort() : Car() {
   registerProperty(color_of_fancy_dashboard, "The color of the fancy dashboard");
   }
};
What happens here is that FordEscord gets created, the typeid for the class (as obtained from this) becomes: class FordEscort * color_of_fancy_dashboard is added to the properties list, as expected. All this would be okay as long as the base class, Car, didn't initialize any properties of its own. There are three possible solutions as far as I can see - do not use inheritance (which doesn't reallt seem like a grand idea), add manual registering of inherited classes, which could be something like this: registerProperty(dashboard, "The color of the fancy dashboard", "Car::"); (however, this would be confusing when the level of inheritance got to 3 or 4, not to mention troublesome) or figure out a way to replace typeid(this) with something more flexible, which would replace: class FordEscort * with something like class Car::FordEscort * I don't see a way to accomplish the third solution. using __FUNCTION__ inside the constructor, too, only returns the current class level, such as: FordEscort::FordEscort but no reference to the base class(es). Since __FUNCTION__ is a precompiler macro, I suppose getting inheritance information to be included in it shouldn't be too difficult. In theory. Of course, there's a fourth solution - one which I'm trying to avoid: since the base class and inherited classes all have the same base pointer (this always points to the same memory address), there would be a way to do a master lookup search among all registered class instances based on the base pointer each time "instantiation" occurs (twice for a first-level inhertied class). However, suppose the number got up to 20000 and new instances were created and destroyed at, say, 500 per second? edit: on second thought, if 500 instances of a class were created and destroyed each second, obtaining member variable references to them would be kind of stupid to start out with. Still - doesn't the language or the precompiler provide a more elegant means? Additionally, is there a way of getting class name information at compile time inside the body of a class, but outside the body of a function?

Share this post


Link to post
Share on other sites
Advertisement
Quote:
Original post by irreversible
edit: on second thought, if 500 instances of a class were created and destroyed each second, obtaining member variable references to them would be kind of stupid to start out with.


Glad you noticed [grin], use pointer to data members (not member functions), still i don't think you'll find an automated non-intrusive solution. What exactly are you trying to do and what is it for?

Share this post


Link to post
Share on other sites
Quote:
Original post by snk_kid
Quote:
Original post by irreversible
edit: on second thought, if 500 instances of a class were created and destroyed each second, obtaining member variable references to them would be kind of stupid to start out with.


Glad you noticed [grin], use pointer to data members (not member functions), still i don't think you'll find an automated non-intrusive solution. What exactly are you trying to do and what is it for?


Suppose you have 15-something (or 100, or 20000) classes that you want to interface with through the UI. Now suppose you're not feeling like writing a user interface for each of them, but you could quite trivially generate a user interface based on the type and number of properties that a class has. But you also need to change all of the variables through the UI.

There you go :).

Anyway, I found a semi-elegant solution that is somewhat intrusive, but should work. This is just demo code that shows how multiple inheritance is maintained whilst intruding as little as possible.


#define defineConstructor(thisclass, baseclass) thisclass(char * __classname__ = #thisclass) : baseclass(__classname__)

interface IBaseInterface
{
private:

public:
IBaseInterface(char * derivative) { out << "CREATED: " << derivative << endl; }
~IBaseInterface() { removeClassInstance(); }
};

class Properties { public: Properties() { } };

class Car : private IBaseInterface, Properties
{
public:
defineConstructor(Car, IBaseInterface), Properties() { }
}

class FordEscort : public Car
{
public:
defineConstructor(FordEscort, Car) { }
}




Calling:

FordEscord myford;

will output "FordEscort" in the constructor for IBaseInterface, where the class can be registered with a proper, derived name. An inheritance tree can easily be biult on this example, too.

The major obstacle this code introduces is a rigid form of the default constructor that also has to be the only constructor for any given class that wants to be logged.

>> use pointer to data members (not member functions)

I didn't mean to imply otherwise :)

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!