基类不完整的继承

Posted

技术标签:

【中文标题】基类不完整的继承【英文标题】:Inheritance with incomplete base class 【发布时间】:2014-04-02 14:41:05 【问题描述】:

我有一个关于概念的问题。首先,我是一名机械工程师而不是程序员,因此我有一些 C++ 知识但没有太多经验。我使用有限元法 (FEM) 来求解偏微分方程。

我有一个基类 Solver 和两个子类 linSolver,用于线性 FEM,nlinSolver 用于非线性 FEM。两个孩子共享的成员和方法都在基类中。基类成员都是protected。因此,使用继承使子类“易于使用”,就像没有任何继承或其他边界一样。基类本身 Solver 是不完整的,这意味着只有子类对我有用。

这个概念实际上很好用——但我认为有一个不可用的类是一个糟糕的设计。此外,我读到protected 继承不是首选,应尽可能避免。我认为最后一点并不真正适用于我的具体用途,因为我永远不会使用它,任何尝试这样做都会失败(因为它不完整)。

问题是:

即使基类不可用,使用继承来减少重复代码是否常见? 对于此类问题,有哪些替代方案或更好的解决方案? protected 继承真的很糟糕吗?

感谢您的宝贵时间。 尼尔

【问题讨论】:

【参考方案1】:

拥有“不可用”的基类实际上很常见。您可以让基类定义一个可由继承基类的类使用的通用接口。如果您声明这些接口函数virtual,您可以使用例如将调用基类的引用或指针以及继承的类对象中的正确函数。

像这样:

class Base

public:
    virtual ~Base() 

    virtual void someFunction() = 0;  // Declares an abstract function
;

class ChildA : public Base

public:
    void someFunction()  /* implementation here */ 
;

class ChildB : public Base

public:
    void someFunction()  /* other implementation here */ 
;

有了上面的类,你就可以做到了

Base* ptr1 = new ChildA;
Base* ptr2 = new ChildB;

ptr1->someFunction();  // Calls `ChildA::someFunction`
ptr2->someFunction();  // Calls `ChildB::someFunction`

但是这不起作用:

Base baseObject;  // Compilation error! Base class is "unusable" by itself

虽然上面的(工作)示例很简单,但请考虑将指针传递给函数时可以做什么。您可以使用一个单独的函数来获取一个指向基类的指针,而不是让两个重载函数分别获取实际类,并且编译器和运行时系统将确保调用正确的(虚拟)函数:

void aGlobalFunction(Base* ptr)

    // Will call either `ChildA::someFunction` or `ChildB::someFunction`
    // depending on which pointer is passed as argument
    ptr->someFunction();


...

aGlobalFunction(ptr1);
aGlobalFunction(ptr2);

即使基类直接“不可用”,它仍然提供一些功能,这些功能是 C++ 可以(并且是)使用的核心的一部分。

当然,基类不必全是接口,它可以包含其他通用 (protected) 辅助函数或实用函数,这些函数可以从继承基类的所有类中使用。请记住,继承是类之间的“is-a”关系。如果您有两个不同的类都“是”某物,那么使用继承可能是一个很好的解决方案。

【讨论】:

【参考方案2】:

您应该检查Abstract class 的概念。 它旨在提供无法实例化的基类。 为此,您在基类中至少提供一种方法,如下所示

virtual void f()=0;

每个孩子都必须重写 f 函数(或任何来自基类的纯虚函数)才能被实例化。

【讨论】:

【参考方案3】:

不要将 BaseClass 本身视为一个类,而是将其视为接口契约和一些实现帮助。因此,它应该是抽象的,如果有必要通过声明 dtor 纯虚拟但无论如何提供实现。一些 OO 纯粹主义者可能不赞成任何非私有元素,但纯粹不是一个好的目标。

【讨论】:

以上是关于基类不完整的继承的主要内容,如果未能解决你的问题,请参考以下文章

为啥我的类不继承其基类中定义的方法?

当基类不包含数据成员时,是不是仍然需要虚拟继承?

为啥具有私有构造函数的类不阻止从此类继承?如何控制哪些类可以从某个基类继承?

继承对基类私有数据成员的访问(在派生类中继承基类成员函数)

派生类继承基类赋值运算符?

子类继承基类的三种继承方式