C++多重继承,其基类派生自同一个类

did*_*dac 4 c++ inheritance abstract

在尝试重用不同类的代码时,我偶然发现了一个问题.我在这里发帖,希望你们中的一些人能够帮助我.

我有一组派生自同一个类(A)的类(B,C),这些类强制执行某些方法(foo,run).B类实现了这些方法,B和C都提供了其他方法:

#include<iostream>

template<class I, class O>
class A {
public:
    A() {}
    virtual ~A() {}

    virtual void foo() const = 0;     // force implementation of this function
    virtual void run() const = 0;     // force implementation of this function
};

template<class I, class O>
class B : public A<I,O> {
public:
    B() {}
    virtual ~B() {}

    virtual void foo() const {        // implementation for the Base class
        std::cout << "B's implementation of foo" << std::endl;
    }

    virtual void run() const {        // implementation for the Base class
        std::cout << "B's implementation of run" << std::endl;
    }

    virtual void foobar() const {     // some other function provided by this class
        std::cout << "B's implementation of foobar" << std::endl;
    }
};

template<class I, class O, class M>
class C : public A<I,O> {
public:
    C() {}
    virtual ~C() {}

    virtual void bar(M m) const {     // some other function provided by this class
        std::cout << "C's implementation of bar with: " << m << std::endl;
    }
};
Run Code Online (Sandbox Code Playgroud)

现在,我想要做的是从B和C继承,以便我可以拥有额外的方法(foobar,bar),但也不必从A类(foo)实现该方法,因为它已经在B中定义:

template<class I, class O>
class D : public B<I,O>, public C<I,O,int> {
public:
    D() {}

    void run() const {
        this->bar(123);
        this->foo();
        this->foobar();
    }
};
Run Code Online (Sandbox Code Playgroud)

但由于某种原因,编译器给了我这个错误:

test.cpp:在函数'int main(int,char**)'中:test.cpp:68:35:error:无法分配抽象类型'D <float,double>'的对象

一个<float,double>*d = new D <float,double>(); // 我需要做什么

test.cpp:48:11:注意:因为以下虚函数在'D <float,double>'中是纯粹的:

D类:公共B <I,O>,公共C <I,O,int> {

    ^
Run Code Online (Sandbox Code Playgroud)

test.cpp:9:22:注意:void一个<I,O> :: foo()const [with I = float; O =双]

virtual void foo()const = 0; //强制执行此功能

这是我用来运行它的代码:

int main(int argc, char **argv)
{

    A<float, double> *b = new B<float, double>();
    b->foo();                                            // prints "B's implementation of foo"
    b->run();                                            // prints "B's implementation of run"

    //A<float, double> *c = new C<float, double, int>(); // obviously fails because C does not implement any of A's functions

    //A<float, double> *d = new D<float, double>;        // line 68: what I need to do
    //d->run();                                          // ***throws the abstract class error

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我想从指向A的指针使用D类对象的'run'函数.由于所有函数都是虚函数,我希望执行在最低继承点中定义的每个函数的实现,这意味着'B :: run '将被丢弃.由于'D :: run'使用来自B和CI的函数,因此需要从这两个类继承.

我希望我已经足够描述它并且不会混淆任何人.谢谢您的帮助!

cdh*_*wie 6

如果您更改BC虚拟继承A模板类,它们将在合并时共享一个基本实例,D并且此错误将消失:

template<class I, class O>
class B : virtual public A<I,O> {

// ...

template<class I, class O, class M>
class C : virtual public A<I,O> {
Run Code Online (Sandbox Code Playgroud)

然而,这种模式(称为钻石继承(反)模式)可能很难推理,我强烈建议尽可能避免使用它.您可能会在以后遇到更加模糊的问题.


以下是此技术的一个示例,但显示了一些乍看之下可能无法预料到的结果:

class A {
public:
    virtual void foo() = 0;
};

class B : virtual public A {
public:
    virtual void foo() override;
};

void B::foo()
{
    std::cout << "B::foo()" << std::endl;
}

class C : virtual public A { };

class D : public B, public C { };

int main() {
    D d;
    C & c = d;

    c.foo();

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

请注意,即使您正在调用C::foo(),这是纯虚拟的,因为只有一个A实例,继承的纯虚函数B::foo()通过共享Avtable 解析.这是一个有点令人惊讶的副作用 - 您可以最终调用在表兄弟类型上实现的方法.