   [c++] extending to allow derived classes in a container
  I apologize for the weird subject line -- it was the best I could come up with.  :)I've currently got a fairly large, base class which has three containers which hold data to other structures:struct DataA { int a; };struct DataB { int b; };struct DataC { float c; };class SomeBigBaseClass{public:    ...lots of public stuff...protected:    virtual void doSomethingWithA(DataA *a) = 0;    virtual void doSomethingWithB(DataB *b, int val) = 0;private:    std::vector<DataA> mAList;    std::vector<DataB> mBList;    std::vector<DataC> mCList;};Other classes derive from SomeBigBaseClass, and implement the virtual functions.  I've been finding that depending on the derived classes' implementation, I need to "attach" extra data to some or all of the DataA, DataB, or DataC classes.  Currently I make a separate struct, adding the extra variables I need, then use a lookup method to map the base DataA pointer to my separate version:struct MyDataA { int my_a; };struct MyDataC { double my_c; };class DerivedClass : public SomeBigBaseClass{protected:    virtual void doSomethingWithA(DataA *a)    {   // map DataA pointer to MyDataA pointer, then use both DataA and MyDataA...    }    virtual void doSomethingWithB(DataB *b, int val) { }private:    std::vector<MyDataA> mDataAList;    std::vector<MyDataC> mDataCList;};While this does work, it seems like there's a got to be a better (and cleaner) way to implement it.My first instinct was to make SomeBigBaseClass a template:template <class TA = DataA, class TB = DataB, class TC = DataC>class SomeBigBaseClass{public:    ...lots of public stuff...protected:    virtual void doSomethingWithA(DataA *a) = 0;    virtual void doSomethingWithB(DataB *b, int val) = 0;private:    std::vector<TA> mAList;    std::vector<TB> mBList;    std::vector<TC> mCList;};This would allow me to derive from the base Data* objects, pass them to the construction of the base class, and the containers would then use the specified classes.  The only problem I have with this is SomeBigBaseClass really is quite large, and by making it a template, I would need to shift all of the code out of the .cpp file and move it into the header -- not something I want to do.Do any of the gurus out there have any other suggestions or ideas on how this could be handled better?  Thanks in advance!   
  Making it a template might be the best solution. Can you tell us more about what the base class actually does, and what the derived classes do? And what are the data objects? I suspect that if the functionality can be broken down into smaller, simpler classes it would help with the problem.   ;  Can you make the vectors store pointers instead of actual elements, and then make the data class polymorphic?class Base{public:  virtual DataA* NewDataA() { return new DataA; }  virtual ~Base() { /* for each i in mAList, delete i */ }  void DoStuff()  {    mAList.push_back( NewDataA() );  }private:  std::vector<DataA*> mAList;};class Derived{public:  virtual DataA* NewDataA() { return new MyDataA; }};[edit]Quote:Original post by rip-offI suspect that if the functionality can be broken down into smaller, simpler classes it would help with the problem.Seconded ;)   ;  This code is from our sound engine.  The SomeBigBaseClass is the base Device class, and the hardware-specific implementations (WaveOut, DirectSound, GBA, NDS, etc) derive from Device.  There's also a software mixing layer that slides in as a derived Device itself, and devices which can't do hardware mixing derive from that software mixing Device.Each of the Data types are structures to channel info, sample data, or stream data.The base Device class has to implement quite a bit of functionality, and I was hoping I could get by without having to expose it all to the outside world just for the luxury of storing derived data structures internally.  :)Any other suggestions, perhaps?   ;Quote:Original post by HodgmanCan you make the vectors store pointers instead of actual elements, and then make the data class polymorphic?That's certainly one option -- but if possible, I would like the data structures to be linear in memory to avoid lots of small memory allocations and fragmentation.Although, an alternative extension to your idea would be to return a reference to a std::vector<> in the derived class, rather than just the individual structs themselves.  The base class could contain it's own std::vector<> as well, but just not directly access it, using only the virtual call to get a reference to the desired container.Now that I think about it, this may not be such a bad solution.  :)   ;  It sounds like you're using inheritance to facilitate code-reuse for each of your devices. Composition is much better suited for this purpose.Instead of reusing code in your derived class like this:class BigClass{  void DoStuffA();  void DoStuffB();  vector<A> dataA;  vector<B> dataB;}class Derived : public BigClass{};You can do it like this:class BigInterface{  virtual void DoStuffA();  virtual void DoStuffB();};tempalte<class T>class SmallClassA{  void DoStuff();  vector<T> data;}tempalte<class T>class SmallClassB{  void DoStuff();  vector<T> data;}class Derived : public BigInterface{  virtual void DoStuffA() { a.DoStuff(); }  virtual void DoStuffB() { b.DoStuff(); }  SmallClassA<MyDataA> a;  SmallClassA<MyDataB> b;};Quote:Original post by bpointQuote:Original post by HodgmanCan you make the vectors store pointers instead of actual elements, and then make the data class polymorphic?That's certainly one option -- but if possible, I would like the data structures to be linear in memory to avoid lots of small memory allocations and fragmentation.I still think that's your best option. If you are worried about memory issues I would use a custom heap that optimizes for your particular usage. You can write own or find one online. Just keep in mind the memory always has to come from somewhere and be managed somehow. Just because you don't see it in vector doesn't mean it's not happening. That's why I tend to write my own containers. I always know exactly what's going on and I never get into trouble with hidden problems (yes you can go ahead and flame me now :-) ). It's really not that hard to do either. The other thing is you can use smart pointers in your vectors. That way you don't even have to worry about memory leaks. I like reference counting because it's a simple model and doesn't get you into trouble too much. If you ever need back-pointers like in a tree or something you just use regular pointers for the back pointers so you don't get reference loops. It's kind of dependant on your exact application.