3

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

  • 1
    Or change `class Derived1: public Base` to `class Derived1: public Base_Ext` – Some programmer dude Jun 21 '21 at 17:31
  • 3
    There is no good way to change the interface without breaking binary compatibility. This is why they are often considered immutable, and any change to the interface requires creating new interface altogether, without shoe-horning original implementation into it. – SergeyA Jun 21 '21 at 17:35
  • 1
    Which types are you trying to preserve binary compatibility for? All types? Just `Base`? – Drew Dormann Jun 21 '21 at 17:36
  • @drew dorman all types – Rohan Uprety Jun 21 '21 at 17:58
  • If your `Base_ext` is required to inherit from `Base`, then your `Base_ext` can be derived from `Base` and 'Base_new'. This `Base_new` will group up your new methods you'd want to share with children of `Base`. That is, your `Derived_x` inherits from `Derived1`, `Base` and `Base_new`. – Hello Everyone Jun 21 '21 at 20:14

1 Answers1

1

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;
    }
}
  • @Sergery How can access the new method using OtherBase pointer OtherBase. *p1; Base. *p = new Derived2();. can i cast p to p1 – Rohan Uprety Jun 21 '21 at 18:10