从一个抽象基类的多个部分实现继承?(Inherit from multiple partial im

2019-07-30 14:50发布

是有可能有许多的抽象接口的部分实现的,然后通过使用多个传承收集这些部分实现成一个单一的具体类

我有下面的代码示例:

#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;
}

这种失败,出现以下错误编译:

main.cpp: In function ‘int main()’:
main.cpp:27:11: error: cannot declare variable ‘d’ to be of abstract type ‘Deriv’
main.cpp:19:8: note:   because the following virtual functions are pure within ‘Deriv’:
main.cpp:5:18: note:    virtual void Base::F1()
main.cpp:6:18: note:    virtual void Base::F2()

Answer 1:

尝试几乎继承自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; }
};

如果没有虚拟继承,你的多重继承的场景看起来像继承来自两个独立的和不完整的基础类D1D2 ,两个国家都不能被实例化。



Answer 2:

是有可能有许多的抽象接口的部分实现的,然后通过使用多个传承收集这些部分实现成一个单一的具体类?

是。

每个Base基类子对象带来了两个纯虚函数。 如何将这些基地的子对象的很多,你在想Deriv

  • 如果你想2 Base的基类的子对象, Deriv::D1::BaseDeriv::D2::Base (因此转换从Deriv&Base&将是不明确的),那么你将有4个不同的虚拟功能在DerivDeriv::D1::Base::F1() Deriv::D1::Base::F2() Deriv::D2::Base::F1() Deriv::D2::Base::F2() 只有第一和最后的实施,所以两个中间的有纯虚: Deriv::D1::Base::F2() Deriv::D2::Base::F1() 你有两个完全独立的继承关系: Deriv继承自D1Deriv从继承D2
  • 如果你只需要一个Base的基础类子对象Deriv::Base ,那么你将有只有2个不同的虚拟功能DerivBase::F1() Base::F2()

在C ++中的非虚拟继承是“混凝土”继承,像遏制: struct D : B意味着对于每个D对象恰好有一个B基类子对象,就像struct C { M m; } struct C { M m; }意味着对于每个C恰好有一个M类成员子对象。 这些关系是一个对一个。

OTOH,虚拟继承是一个比较“抽象”: struct D : virtual B意味着对于每个D对象与相关联的B基类子对象,但这种关系是多到一个,如struct C { M &m; } struct C { M &m; }

通常,对于任何派生类D (此处Deriv ),以及用于任何虚拟基BD (此处Base )的所有基类D几乎衍生自B (这里Deriv::D1Deriv::D2 )向的在基类的虚拟函数压倒一切的:

  • Base::F1()由重写Deriv::D1::F1()
  • Base::F2()由重写Deriv::D2::F2()

非虚拟和虚拟继承是非常不同的继承关系,就像如果非虚拟成员函数和一个虚函数中引入功能之间不同的关系具有相同签名的派生和基类(隐藏与首要)。

像虚拟和非虚函数,虚拟和非虚拟基类必须在不同的情况下使用(有一个没有通常比其他的“更好”)。

如何“修理”你的代码,而虚拟继承?

 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; }; 

是:使用申报控制名称查找,所以他们的影响可见性和模糊性问题,而不是虚函数覆盖。

有了您的原非虚继承为基础的设计,为了使Deriv一个具体的类,你必须明确地实现这两个F1()F2()虚函数签名(有4个虚函数Deriv ,但只有2个不同签名),所以你需要2下函数的定义:

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

需要注意的是Deriv::F1()覆盖Deriv::D1::F1()Deriv::D2::F1()



文章来源: Inherit from multiple partial implementations of an abstract base class?