c ++另一个基类中的抽象类实现

时间:2015-03-26 20:33:16

标签: c++ virtual-inheritance

问题

为什么不尝试虚拟继承,如果它似乎解决了我的钻石继承问题?

简报:

在学习C ++时,我遇到了以下代码的一些编译器错误:

#include <stdlib.h>
#include <iostream>

class IFoo{
    public:
    virtual void Hello() = 0;
};

class Foo : public IFoo{
    public:
    void Hello()
    {
        printf("Hello");
    }
};

class IBar : public IFoo{
    public:
    virtual void HelloWorld() = 0;
};

class Bar : public IBar, public Foo{
    public:
    void HelloWorld()
    {
        Hello();
        printf("World");
    }
};

int main()
{
    Bar b;
    b.HelloWorld();

    system("pause");
    return 0;
}

我希望Bar实现抽象类IBar,它将IFoo作为基类,但后来我想要由Bar的第二个基类Foo提供的所有IFoo实现。

我得到2个编译器错误(GCC 4.9.2):一个与歧义有关,另一个与抽象类IFoo缺少实现有关。

然后我找到了this question并且满足了虚拟继承的概念,这导致我this page。在本教程之后,我添加了虚拟继承,所有问题都消失了:

class Foo : public virtual IFoo{...
class IBar : public virtual IFoo{...

但是question中的用户建议不要尝试虚拟继承。因此我的问题。

2 个答案:

答案 0 :(得分:0)

Hello()中的Bar::HelloWorld()来电是不明确的。编译器无法判断您是否尝试从Hello()IBar拨打Foo。您可以在其中调用Foo::Hello()IBar::Hello()。话虽如此,你的继承结构并没有多大意义。

您的Bar课程还需要覆盖从Hello继承的IBar

如果你有c ++ 11,最好用override关键字标记你要覆盖的虚拟函数:

#include <stdlib.h>
#include <iostream>

class IFoo{
    public:
    virtual void Hello() = 0;
};

class Foo : public IFoo{
    public:
    virtual void Hello() override
    {
        printf("Hello");
    }
};

class IBar : public IFoo{
    public:
    virtual void HelloWorld() = 0;
};

class Bar : public IBar, public Foo{
    public:
    virtual void HelloWorld() override
    {
        Foo::Hello();
        printf("World");
    }

     void Hello() override {}
};

int main()
{
    Bar b;
    b.HelloWorld();

    system("pause");
    return 0;
}

要回答关于虚拟继承的问题,您可以轻松地将继承结构更改为仍可以避免菱形图案的工作。很少需要钻石图案,通常可以避免:

#include <stdlib.h>
#include <iostream>

class IFoo{
public:
    virtual void Hello() = 0;
};

class Foo : public IFoo{
public:
    virtual void Hello() override
    {
        printf("Hello");
    }
};

class IBar {
public:
    virtual void World() = 0;
};

class Bar : public IBar{
public:
    virtual void World() override
    {
        printf("World");
    }
};

class FooBar : public Foo, public Bar
{
public:
    virtual void HelloWorld()
    {
        Hello();
        World();
    }
};

int main()
{
    FooBar b;
    b.HelloWorld();

    system("pause");
    return 0;
}

答案 1 :(得分:0)

你的班级

Bar

必须覆盖

Hello

否则类Bar也变得纯粹抽象,因为

Hello

继承
IFoo.

每当一个类继承一个abtract基类时,它必须实现所有基类&#39;纯虚函数,否则派生类本身也变得抽象。

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

// this class is abstract, it doesn't implement Base::foo
class Derived1 : public Base{
public:
    void fooDerived() {}
};

// this class is not abstract, it implements Base::foo
class Derived2 : public Base{
public:
    void foo() {}
};

正如另一个答案中所建议的,在C ++ 11中,您可以使用override关键字声明该函数,这可以确保该函数覆盖虚拟函数。像这样:

   // this class is not abstract, it implements Base::foo
class Derived2 : public Base{
public:
    void foo() override {}
};

虚拟继承解决了另一个问题,即从多个声明相同函数或成员的基类继承时出现歧义问题。