C++ 从抽象基类的多个部分实现继承?

C++ 从抽象基类的多个部分实现继承?,c++,multiple-inheritance,virtual-inheritance,C++,Multiple Inheritance,Virtual Inheritance,一个抽象接口是否可以有多个部分实现,然后使用多个继承将这些部分实现收集到一个具体类中 我有以下示例代码: #include <iostream> struct Base { virtual void F1() = 0; virtual void F2() = 0; }; struct D1 : Base { void F1() override { std::cout << __func__ << std::endl; } };

一个抽象接口是否可以有多个部分实现,然后使用多个继承将这些部分实现收集到一个具体类中

我有以下示例代码:

#include <iostream>

struct Base
{
    virtual void F1() = 0;
    virtual void F2() = 0;
};

struct D1 : Base
{
    void F1() override { std::cout << __func__ << std::endl; }
};

struct D2 : Base
{
    void F2() override { std::cout << __func__ << std::endl; }
};

// collection of the two partial implementations to form the concrete implementation
struct Deriv : D1, D2
{
    using D1::F1; // I added these using clauses when it first didn't compile - they don't help
    using D2::F2;
};

int main()
{
    Deriv d;
    return 0;
}
Base
尝试:

struct D1 : virtual Base
{
    void F1() override { std::cout << __func__ << std::endl; }
};

struct D2 : virtual Base
{
    void F2() override { std::cout << __func__ << std::endl; }
};
结构D1:虚拟基 { void F1()重写{std::cout 一个抽象接口可以有许多部分实现,然后使用多个继承将这些部分实现收集到一个具体类中吗

每个
Base
基类子对象都会带来两个纯虚函数。您希望在
Deriv
中包含多少基类子对象

  • 如果您想要2
    Base
    Base子对象、
    Deriv::D1::Base
    Deriv::D2::Base
    (因此从
    Deriv&
    Base&
    的转换将是不明确的),那么您将在
    Deriv
    Deriv::D1::Base::F1()
    Deriv::D1::Base::F2()中有4个不同的虚拟函数
    Deriv::D2::Base::F1()
    Deriv::D2::Base::F2()
    。只实现了第一个和最后一个,所以中间的两个是纯虚拟的:
    Deriv::D1::Base::F2()
    Deriv::D2::Base::F1()
    。您有两个完全独立的继承关系:
    Deriv
    继承自
    D1
    Deriv
    继承自
    D2
  • 如果只需要一个
    Base
    Base类子对象
    Deriv::Base
    ,则在
    Deriv
    中只有两个不同的虚拟函数:
    Base::F1()
    Base::F2()
<> > C++中的非虚继承是“具体的”继承,如包容:<代码>结构>:b/COD>意味着对于每个<代码> d< /Cord>对象,恰好有一个<代码> b>代码>基类SubBobe,就像StultC{m m;}意味着对于每个
C
来说,只有一个
M
类成员子对象。这些关系是一对一的

另外,虚拟继承是一种更“抽象的”:
struct D:virtual B
意味着每个
D
对象都与
B
基类子对象相关联,但这种关系是多对一的,就像
struct C{M&M;}

通常,对于任何派生类
D
(此处
Deriv
),以及
D
(此处
base
)的任何虚拟基
B
D
的所有基类都是虚拟派生自
B
(此处
Deriv::D1
Deriv::D2
)有助于重写基类中的虚拟函数:

  • Base::F1()
    Deriv::D1::F1()覆盖
  • Base::F2()
    Deriv::D2::F2()覆盖
非虚继承和虚继承是非常不同的继承关系,就像非虚成员函数和虚函数在派生类和基类中具有相同签名的函数之间引入不同的关系一样(隐藏与重写)

与虚函数和非虚函数一样,虚基类和非虚基类必须在不同的情况下使用(通常一个基类并不比另一个基类“更好”)

如何在没有虚拟继承的情况下“修复”代码? 是:使用声明控件名称查找,因此它们会影响可见性和模糊性问题,而不是虚拟函数重写

对于原始的基于非虚拟继承的设计,为了使
Deriv
成为一个具体的类,您必须显式地实现
F1()
F2()
虚拟函数签名(在
Deriv
中有4个虚拟函数,但只有2个不同的签名),因此您需要2个函数定义:

struct Deriv : D1, D2
{
    void F1() override { D1::F1(); }
    void F2() override { D2::F2(); }
};

请注意,
Deriv::F1()
覆盖了
Deriv::D1::F1()
Deriv::D2::F1()

+1作为一个简短的、自包含的示例。“抽象接口”一般来说:抽象接口意味着虚拟继承(特殊情况可能有所不同)。
struct D1:Base
”这里使用公共继承有什么原因吗?对客户端代码使用
D1
感兴趣吗?@curiousguy没有原因-刚刚举了一个例子-在我的特殊用法中,我使用公共和私有的混合,这取决于“不完整的基类”的情况抽象基类?@curiousguy不一定是抽象的,只要至少有一个未实现的方法。@juanchopanza什么是抽象类?@curiousguy啊哈!我明白你的意思。如果实现的方法是“抽象的”,我仍然很难想象一个有一堆方法的类但我应该尊重C++术语。“好家伙,在那种情况下,我把它全部收回。”
struct Deriv : D1, D2
{
    using D1::F1; // I added these using clauses when it first didn't compile - they don't help
    using D2::F2;
};
struct Deriv : D1, D2
{
    void F1() override { D1::F1(); }
    void F2() override { D2::F2(); }
};