在不破坏现有基类的情况下向具有许多派生类的抽象基类添加新方法

Posted

技术标签:

【中文标题】在不破坏现有基类的情况下向具有许多派生类的抽象基类添加新方法【英文标题】:Adding new method to Abstract Base class which has many derived classes without breaking existing base class 【发布时间】:2021-09-05 09:09:35 【问题描述】:

我有一个抽象基类。有很多抽象类派生自这个抽象基类

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

例如

    #if ABI_VERSION_ATLEAST1
    class Derived1: public Base
    
    ;
   #endif

假设我想在不破坏二进制兼容性的情况下为其添加新方法。 唯一的办法就是扩展这个类

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

问题是已经存在的派生类实现将无法访问这个 food1()。 怎么解决这个问题 抽象派生类怎么能看到这个新方法

我想到的一个解决方案是:-

我需要扩展 Derived1.......

#if ABI_VERSION_ATLEAST2

class Derived2 : public Derived1, public Base_Ex
 
 ;

#endif 

再次在这里解决钻石问题,我将不得不改变

class Derived1: public Base to

 class Derived1: public virtual Base  

我不想这样做..因为它会再次破坏现有派生类的二进制兼容性。所以坚持下去

【问题讨论】:

或者把class Derived1: public Base改成class Derived1: public Base_Ext 没有什么好的方法可以在不破坏二进制兼容性的情况下更改界面。这就是为什么它们通常被认为是不可变的,并且对接口的任何更改都需要完全创建新接口,而不是硬塞原始实现。 您要为哪些类型保留二进制兼容性?所有类型?就Base? @drew dorman 所有类型 如果您的Base_ext 需要从Base 继承,那么您的Base_ext 可以从Base 和'Base_new' 派生。这个Base_new 将汇总您想与Base 的孩子分享的新方法。也就是说,您的Derived_x 继承自Derived1BaseBase_new 【参考方案1】:

您可以创建第二个基类,我们将其命名为OtherBase,您可以在其中添加新方法。 你可以创建新的派生类,我们命名为Derived2,它继承了OtherBaseDerived1的方法:

#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 如何使用OtherBase 指针OtherBase 访问新方法。 *p1;根据。 *p = 新的 Derived2();。我可以将 p 转换为 p1

以上是关于在不破坏现有基类的情况下向具有许多派生类的抽象基类添加新方法的主要内容,如果未能解决你的问题,请参考以下文章

不是抽象类的基类不是好基类

设计模式总结

抽象派生类中的抽象方法覆盖/实现抽象基类的抽象或具体方法。如何以及为啥?

使用具有抽象基类指针并调用派生类函数的映射

c ++是不是可以在不基于其基类的派生类中创建构造函数?

类的继承与派生