1

I have an abstract base class called Base that other programmers are to write implementations for. In some other part of the application, I want to catch all implementations that have been written and construct a single instance of each. If this could be done with no additional instructions to others beyond "implement Base", that would be beautiful. However, the code I have below, requires that each implementation register itself. It also doesn't work.

#include <iostream>
#include <vector>

class Base;

std::vector<Base*>* registrationList = new std::vector<Base*>;

class Base {
public:
   Base(){}
   virtual void execute() = 0;
};

class ImplementationOne: public Base {
public:
   ImplementationOne(){registrationList->push_back(this);}
   void execute(){std::cout << "Implementation One." << std::endl;}
   static int ID;
};

class ImplementationTwo: public Base {
public:
   ImplementationTwo(){registrationList->push_back(this);}
   void execute(){std::cout << "Implementation Two." << std::endl;}
   static int ID;
};

int main(int argc, const char * argv[]){
   std::cout << "Registration List size: " << registrationList->size() << std::endl;
   for(auto it = registrationList->begin() ; it != registrationList->end() ; ++it){
      (dynamic_cast<Base*>(*it))->execute();
   }
   return 0;
}

I get an output of: Registration List size: 0, so it is clear that the implementations were never instantiated. It is probably obvious that this wouldn't happen, but I am a beginner and this is the best I could come up with. I assumed that static int ID; would force instantiation of each implementation, which would then register themselves. I can see static does not result in instantiation. I leave it in my code here since it shows my intent.

What can I do to get automatic instantiation of each implementation? Is it possible?

Little Endian
  • 784
  • 8
  • 19

2 Answers2

1

Adding static members does not cause an instance to be generated, it merely declares that this type has a "global" variable. You never actually defined these members though, so if you tried to use them for anything you would have had a linker error. You'll have to actually instantiate an object and register that.

One solution might be to simply require each derived type to register an instance at startup. This is actually quite easily done, as I show here. (Note I moved your global to a static local of a static function. This prevents several problems you haven't run into yet, including providing an "owner" for the global.)


Unrelated to your issue, your code has problems:
  • There is almost never any reason to have a pointer to a container.
  • You are deriving polymorphically from a type with no virtual destructor.
  • You dynamic_cast<Base*> for no apperent reason.
  • Each of your derived classes declares but does not define a ID member.
Mooing Duck
  • 64,318
  • 19
  • 100
  • 158
  • Thanks for the feedback. It looks like you defined the static function `registrationList()` the way you did to get around the problem of defining a static variable `static std::vector registrationList;` in the class definition. I tried editing your code to use a static variable, but got linker errors. – Little Endian Jul 01 '13 at 19:16
  • 1
    Actually that didn't actually cross my mind. What I was thinking of was (A) it's part of the `Base` heiarchy, not global state of the program, and (B) avoiding the [Static Initialization Order Fiasco](http://stackoverflow.com/questions/5299095/static-initialization-order-fiasco) – Mooing Duck Jul 01 '13 at 19:20
  • Ah. I figured out how to fix the problem from my comment. Do: `std::vector Base::registrationList;` outside class definition. – Little Endian Jul 01 '13 at 22:11
  • 1
    Don't do that. If you try to scale that design up, you'll run into the Static Initialization Order Fiasco. Make it a function-local static variable. – Mooing Duck Jul 01 '13 at 22:16
0

Of course the vector is empty, you never add anything to the it. The constructors of the derived classes are not called since you never create any object instances of them.

Just because you have static members doesn't mean any object instances will be created. It just guarantees that value will be the same between different instances.

You have to explicitly create instances of the classes to have the constructor being called.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621