Search code examples
c++derived-class

Deduct real type of object from base class pointer to create copy


I have base class and a lot of classes derived from if. I want to create object copy. Is there a way to deduct real type of object under pointer to base class without dynamic_cast or implementation of createCopy in every derived class?

Something like this:

class Base {
public:
    Base(){};
    virtual ~Base() = default;
    virtual void fun() = 0;

    Base *createCopy()
    {
        return new /*some way to deduct real "this" type */
    }
};

class Derived1 : public Base
{
public:
    Derived1() : Base(){};
    virtual void fun() { /* impl */ };
};

class Derived2 : public Base
{
public:
    Derived2() : Base(){};
    virtual void fun() { /* impl */ };
};

/* Derived3 - Derived8999 implementation*/

class Derived9000 : public Base
{
public:
    Derived9000() : Base(){};
    virtual void fun() { /* impl */ };
};

int main()
{
    Base *pObj = new Derived9000; // pObj type is Derived9000*

    Base *pCopy = pObj->createCopy(); // pCopy type is Derived9000*
}

Solution

  • You can do this in two ways. You can store the type in a middle layer like this:

    class Base {
    public:
        Base(){};
        virtual ~Base() = default;
        virtual void fun() = 0;
        virtual Base *createCopy() = 0;
    };
    
    template <typename Type>
    class MiddleBase : public Base {
    public:
        MiddleBase(){};
        virtual void fun() = 0;
    
        Base *createCopy() final override
        {
            return new Type();
        }
    };
    
    class Derived1 : public MiddleBase<Derived1>
    {
    public:
        Derived1() : MiddleBase(){};
        virtual void fun() { /* impl */ };
    };
    
    class Derived2 : public MiddleBase<Derived2>
    {
    public:
        Derived2() : MiddleBase(){};
        virtual void fun() { /* impl */ };
    };
    
    /* Derived3 - Derived8999 implementation*/
    
    class Derived9000 : public MiddleBase<Derived9000>
    {
    public:
        Derived9000() : MiddleBase(){};
        virtual void fun() { /* impl */ };
    };
    
    int main()
    {
        Base *pObj = new Derived9000; // pObj type is Derived9000*
        Base *pCopy = pObj->createCopy(); // pCopy type is Derived9000*
    }
    

    Or IMO a better way you could just let the copy function be overloaded by the specific types and just let each type handle its copy:

    class Base {
    public:
        Base(){};
        virtual ~Base() = default;
        virtual void fun() = 0;
        virtual Base *createCopy() = 0;
    };
    
    class Derived1 : public Base
    {
    public:
        Derived1() : Base(){};
        virtual void fun() { /* impl */ };
        Base *createCopy() override {
            return new Derived1();
        };
    };
    
    class Derived2 : public Base
    {
    public:
        Derived2() : Base(){};
        virtual void fun() { /* impl */ };
        Base *createCopy() override {
            return new Derived2();
        };
    };
    
    /* Derived3 - Derived8999 implementation*/
    
    class Derived9000 : public Base
    {
    public:
        Derived9000() : Base(){};
        virtual void fun() { /* impl */ };
        Base *createCopy() override {
            return new Derived9000();
        };
    };
    
    int main()
    {
        Base *pObj = new Derived9000; // pObj type is Derived9000*
        Base *pCopy = pObj->createCopy(); // pCopy type is Derived9000*
    }