在其他父分支中实现虚拟方法而不是声明它们

时间:2011-08-04 17:14:23

标签: c++ virtual multiple-inheritance

我有以下代码:

#include <iostream>

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

class Mom : public Grandma{};

class Dad
{
public:
    void foo() { std::cout << "dad's foo impl"; }
};

class Me : public Mom, public Dad{};

int main()
{
    Me m;
    m.foo();
}

并获得:cannot instantiate abstract class

我知道这个错误意味着什么,我知道我不能因为纯粹的虚拟而实例化奶奶。

但是为什么我不能实例化我,当编译器知道我是从爸爸妈妈那里得到的,爸爸已经实现了foo

我知道我可以通过将foo添加到Me并在其内部调用来解决此问题。 Dad::foo,但我担心这不适合我的案例。

是否真的有必要在其声明和实例化对象之间实现虚拟方法(在遍历“类层次结构图”时)?参见ASCI图

    A
    |
B1  B2
  \ |   
   C1  C2
    | /
    |/
    D
    |
    E

当我想实例化E并在A中有虚拟声明时,使其运行的唯一方法是在A,B2,C1,D或E中定义它? 类似地,当C2中的虚拟声明只有在C2,D或E中定义它时?

我知道这可能是一个愚蠢的问题,但我有一个漫长的一天,不能再想了。

请不要回答 - “这是不可能的”,但是为什么不尝试添加解释。

谢谢!

编辑 - Dad中的foo()当然不应该是私有的

3 个答案:

答案 0 :(得分:4)

Dad类和Grandma类之间存在无关系DadGrandma是两个完全不同的类。鉴于Dad中的方法不被视为Grandma中纯虚方法的实现,必须在Me类中实现。

当您从抽象类(包含至少一个纯虚函数的类)派生时,派生类需要覆盖并实现 ALL 基础的纯虚拟成员函数类。如果没有,则派生类也变为抽象,同样适用于从层次结构中的派生类派生的类。

答案 1 :(得分:1)

不幸的是,你必须在原始声明和最终实例化对象之间的路径中实现虚方法。多次继承的对象无法实现该接口。

因此,从问题来看,您似乎试图通过继承实现者来实现子类中的父接口。您是否考虑让父类将工作委托给策略模式,然后在子类中选择正确的策略,而不是采用这种方法。然后你仍然可以一起编写实现,而不必担心多重继承的许多复杂性。

答案 2 :(得分:1)

您是正确的,虚拟函数只能被从最初声明虚函数的类继承(可能通过多个层)的类提供的实现覆盖。

但是,根据您实际尝试完成的内容,Sister Class Delegation可能是您想要的。基本上,你可以在祖母和爸爸共同的基础上声明虚函数('人'?),即使只有爸爸在你使用Me对象时提供实现,奶奶也可以调用这些函数。即使奶奶对爸爸一无所知,当你使用虚拟继承时,你的最终类所引入的任何子类都可以用来满足虚拟基类中的虚函数。