【问题标题】:Implementing virtual methods in other parent-branch than they are declared in在其他父分支中实现虚拟方法,而不是在其中声明
【发布时间】:2011-08-04 17:14:23
【问题描述】:

我有以下代码:

#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 中定义它?

我知道这可能是个愚蠢的问题,但我度过了漫长的一天,无法再思考了。

请不要只回答“不可能”,而是尝试添加解释为什么不。

谢谢!

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

【问题讨论】:

  • 您的Dad 类不是从Grandma 类派生的,因此Dad::foo 不会覆盖基类纯虚函数。此外,您的派生不是虚拟的,因此您在 Me 中有两个单独的子对象
  • @Gene Bushuyev 这里没有菱形继承,所以虚拟继承应该没有效果。
  • @Mark——没错,但这不是我的意思。如果Dad 是从Grandma 派生的,就会出现菱形,并且同样的错误,使派生虚拟可以解决后者。
  • 是的,爸爸应该有一个妈妈,因此是从奶奶派生出来的。也许只是一个例子的坏名字:)

标签: c++ virtual multiple-inheritance


【解决方案1】:

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

当您从 抽象类(包含至少一个纯虚函数的类)派生时,派生类需要重写并实现 ALL Base 的纯虚成员函数班级。如果不是,派生类也变成抽象类,同样适用于从派生类派生的类。

【讨论】:

  • using Dad::foo 添加到Me 是否足以满足此条件?
  • 如果您避免使用有效的运算符作为单词 and 的缩写,您的答案会更清楚
  • @rcollyer: Dad::fooDad 中是私有的,所以无论如何它都无法访问,考虑到它是protected NO,你仍然需要提供一个实现在Me.
  • @Nicola Musatti:你的意思是用and 替换&amp;,你真的因为这个原因投反对票吗?
  • @Nicola Musatti:我觉得很有趣的是,您会因为 不理解而对某人的回答投反对票。我很高兴虽然 OP 理解了它并询问了 Q 的说明。 :)
【解决方案2】:

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

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

【讨论】:

    【解决方案3】:

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

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

    【讨论】:

      猜你喜欢
      • 2019-07-01
      • 1970-01-01
      • 1970-01-01
      • 2015-02-11
      • 2020-12-17
      • 2012-09-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多