我有以下代码:
#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()当然不应该是私有的
答案 0 :(得分:4)
Dad
类和Grandma
类之间存在无关系。 Dad
和Grandma
是两个完全不同的类。鉴于Dad
中的方法不被视为Grandma
中纯虚方法的实现,必须在Me
类中实现。
当您从抽象类(包含至少一个纯虚函数的类)派生时,派生类需要覆盖并实现 ALL 基础的纯虚拟成员函数类。如果没有,则派生类也变为抽象,同样适用于从层次结构中的派生类派生的类。
答案 1 :(得分:1)
不幸的是,你必须在原始声明和最终实例化对象之间的路径中实现虚方法。多次继承的对象无法实现该接口。
因此,从问题来看,您似乎试图通过继承实现者来实现子类中的父接口。您是否考虑让父类将工作委托给策略模式,然后在子类中选择正确的策略,而不是采用这种方法。然后你仍然可以一起编写实现,而不必担心多重继承的许多复杂性。
答案 2 :(得分:1)
您是正确的,虚拟函数只能被从最初声明虚函数的类继承(可能通过多个层)的类提供的实现覆盖。
但是,根据您实际尝试完成的内容,Sister Class Delegation可能是您想要的。基本上,你可以在祖母和爸爸共同的基础上声明虚函数('人'?),即使只有爸爸在你使用Me对象时提供实现,奶奶也可以调用这些函数。即使奶奶对爸爸一无所知,当你使用虚拟继承时,你的最终类所引入的任何子类都可以用来满足虚拟基类中的虚函数。