views:

701

answers:

4

Suppose I have the following (simplified case):

class Color;

class IColor
{
public: 
    virtual Color getValue(const float u, const float v) const = 0;
};

class Color : public IColor
{
public:
    float r,g,b;
    Color(float ar, float ag, float ab) : r(ar), g(ag), b(ab) {}
    Color getValue(const float u, const float v) const 
    { 
        return Color(r, g, b)
    }
}

class Material
{
private:
    IColor* _color;
public:
    Material();
    Material(const Material& m);
}

Now, is there any way for me to do a deep copy of the abstract IColor in the copy constructor of Material? That is, I want the values of whatever m._color might be (a Color, a Texture) to be copied, not just the pointer to the IColor.

+5  A: 

You could add a clone() function to your interface.

luke
+1  A: 

You'll have to add that code yourself to the Material copy constructor. Then code to free the allocated IColor in your destructor.

You'll also want to add a virtual destructor to IColor.

The only way to do a deep copy automatically would be to store a color directly instead of a pointer to an IColor.

Brian R. Bondy
Why storing a pointer on IColor will disable the deep copy?
Patrice Bernassola
Because by default it will simply copy the pointer address into the copied pointer address. It will not copy what is being pointed to and then re-adjust the pointer. Luke has the best suggestion in making a clone() function called from the copy constructor.
Brian R. Bondy
+11  A: 

Take a look at the virtual constructor idiom

Nemanja Trifunovic
A: 

Adding a clone() method to color is probably best, but if you don't have that option, another solution would be to use dynamic_cast to cast IColor* to Color*. Then you can invoke the Color copy constructor.

Corwin Joy
But you don't know if it is a Color or a Texture, how can you dynamic_cast then ?
Barth
If the object is not of type color then dynamic_cast<Color *>(_color) will return null. (Dynamic cast / rtti can detect what the actual type is as long as the class has at least one virtual method). So what you can do is test the possibilities. This is no fun, and almost always worse then using a clone() method, but there are rare situations where you have to do something like this.
Corwin Joy