Rohan Uprety
Rohan Uprety

Reputation: 61

Adding new method to Abstract Base class which has many derived classes without breaking existing base class

I have a abstract base class . There are many abstract classes which derived from this Abstract Base class

    #if ABI_VERSION_ATLEAST1
    class Base
    {
    public:
      virtual void food() =0
    };
  #endif

for example

    #if ABI_VERSION_ATLEAST1
    class Derived1: public Base
    {
    };
   #endif

Suppose i want to add new method to it, without breaking binary compatibility. The only way is to extend this class

#if ABI_VERSION_ATLEAST2
    class Base_Ext : public Base
    {
    public:
      virtual void food1()=0;
    };
    #endif

The problem is the already existing derived classes implementation wont be able to access this food1(). How to solve this problem How can Abstract Derived classes see this new method

One solution i have in mind is : -

i would need to extend Derived1.......

#if ABI_VERSION_ATLEAST2

class Derived2 : public Derived1, public Base_Ex
{ 
} ;

#endif 

again here to solve diamond problem, I will have to change

class Derived1: public Base to

 class Derived1: public virtual Base {} 

which i dont want to do.. as it would again break binary compatibility of existing derived classes.so stuck at it

Upvotes: 3

Views: 389

Answers (1)

Sergey Aleksandrovich
Sergey Aleksandrovich

Reputation: 236

You can create the second base class, let's name it OtherBase where you can add new methods. And you can create new derived class, let's name it Derived2, which inherits methods from OtherBase and Derived1:

#include <iostream>

class Base
{
public:
  virtual void food() = 0;
  virtual ~Base() {}; // virtual destructor is necessary to avoid memory leak
};

class Derived1 : public Base
{
public:
    virtual void food() override
    {
        std::cout << "Derived1::food" << std::endl;
    }
    virtual ~Derived1() override {}
};

class OtherBase
{
public:
    virtual void food1() = 0;
    virtual ~OtherBase() {}; // virtual destructor is necessary to avoid memory leak
};

class Derived2 : public OtherBase, public Derived1
{
public:
    virtual void food1() override
    {
        std::cout << "Derived2::food1" << std::endl;
    }
    virtual ~Derived2() override {}
};

int main()
{
    std::cout << "On the stack:" << std::endl;
    Derived2 derived2;
    derived2.food();
    derived2.food1();
    
    std::cout << "On the heap:" << std::endl;
    OtherBase * otherBase_p1 = new Derived2();
    if (otherBase_p1) // check if memory was is allocated
    {
        otherBase_p1->food1();
        
        Base * base_p = dynamic_cast<Base *>(otherBase_p1);
        if (base_p) // if dynamic_cast was unsuccessful than base_p is nullptr
        {
            base_p->food();
        }
        
        delete otherBase_p1;
    }
}

Upvotes: 1

Related Questions