Hi, I have a map of a base class object (not pointer to objects). I did this because I need to have inheritance from others types like this:

Parameter
RealParameter: Parameter
IntParameter: Parameter
...

My problem is that when I am going to insert in the map, copy constructur of the base class is called, but really Parameter is only an class with all virtual methods, and all data is in the derived class. How can I develope a copy constructor of a base case class that allows me to copy his derived class associated?


thanks all!

Recommended Answers

All 2 Replies

Very interesting problem! I don't think it's possible to create such a copy constructor for base class since the base class doesn't have a clue of the classes derived from it( and that's the way it should be).

In your case I would use pointers to object in the map and let dynamic binding take care of the rest :)

Hope I understood your problem right so I won't look like an idiot on DaniWeb...

Here are a few facts:
1. If you hold a map of objects (not pointers) of the base class, then it's going to be objects of the base class, not a derived class, that's impossible without a very nasty hack (reinterpret cast on the object). DON'T DO THAT!
2. There is no way to implement a copy-constructor in a base class that will achieve the copy of the derived class, without an even worst and absolutely horrible hack (involving a memmove() on the "this" pointer). DON'T DO THAT!
3. You cannot use a reference to a base object either because references cannot be assigned (or re-seated).

There are many alternatives to achieve what you want, or what I guess you want. Here are a two good ones that I could recommend:
1. use a map of pointers to the base class objects, or better, use smart pointers like std::TR1::shared_ptr<> or std::TR1::unique_ptr<>.
2. use the Pimpl idiom to encapsulate the pointer to the base_impl class and then you can hold and copy the base objects with properly designed methods. This is from a previous post of mine on this thread on a very similar subject:

class BaseClass {
  public:
    class Impl {
      public:
        //Here, you would list all those virtual methods you want.
        virtual void someMethod() = 0; 
        //This methods needs to be implemented in each derived class to call its constructor (with new).
        virtual Impl* clone() throw() = 0; 
        //virtual destructor, of course.
        virtual ~Impl() throw() { };
        //this method will create the base class to encapsulate "this", via the private, implicit constructor of BaseClass.
        BaseClass Encapsulate() throw() { return this; };
    };
  private:
    Impl* pImpl; //pointer to the implementation object.
    //Private default constructor and "cloning" constructor.
    BaseClass(BaseClass::Impl* aImpl = NULL) throw() : pImpl(aImpl) { };
  public:
    //for any "virtual" methods, just forward the call to the implementation pointer.
    //don't worry about efficiency of forwarded calls, because the compiler will optimize this away. 
    void someMethod() { pImpl->someMethod(); };
    //non-virtual destructor.
    ~BaseClass() throw() { delete pImpl; };
    //Copy-constructor that clones the implementation pointer.
    BaseClass(const BaseClass& aObj) throw() : pImpl(aObj.pImpl->clone()) { };
    //Assignment operator that clones the implementation pointer.
    BaseClass& operator =(const BaseClass& aObj) throw() { pImpl = aObj.pImpl->clone(); return *this; };
};

//Now, a typical derived class is derived from BaseClass::Impl instead of BaseClass.
class SubClass1 : public BaseClass::Impl {
  public:
    //Here, implement the virtual methods.
    virtual void someMethod() { .. };
    //Here, provide the clone() method.
    virtual Impl* clone() throw() { return new SubClass1(*this); };
    //Here, provide a valid copy-constructor, if non-POD.
    SubClass1(const SubClass1& aObj) throw() : ... { ... };
    ...
};

int main() {
  //declare a vector (or any STL container) of BaseClass objects.
  std::vector<BaseClass> objects;
  //Create the derived class object and encapsulate it in a BaseClass.
  objects.push_back((new SubClass1)->Encapsulate());
  ...
};
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.