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

c++ abstract class implementation in another base class

本文关键字:实现 基类 另一个 抽象类 c++      更新时间:2023-10-16

问题

如果虚拟继承似乎可以解决我下面的钻石继承问题,为什么不尝试呢?

简报:

在学习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实现以IFoo为基类的抽象类IBar,但我希望Bar的第二个基类Foo提供IFoo的所有实现。

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

然后我发现了这个问题,并遇到了虚拟继承的概念,这将我带到了这一页。在教程之后,我添加了虚拟继承,所有问题都消失了:

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

但有问题的用户建议不要尝试虚拟继承。因此,我提出了这个问题。

您的班级

Bar

必须覆盖

Hello

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

Hello

一直从继承

IFoo.

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

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

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

Bar::HelloWorld()中的Hello()调用不明确。编译器无法判断您是试图从IBar还是Foo调用Hello()。您可以在它的位置调用Foo::Hello()IBar::Hello()。话虽如此,你的继承结构并没有真正意义。

Bar类还需要重写它从IBar继承的Hello

如果您有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;
}