是否可以实现一个抽象基类,其成员继承自C ++中另一个父类?
它适用于C#,所以我尝试用C ++编写:
// Virtual destructors omitted for brevity
class ITalk
{
public:
virtual void SayHi() = 0;
};
class Parent
{
public:
void SayHi();
};
class Child : public Parent, public ITalk
{
};
void Parent::SayHi()
{
std::printf("Hi\n");
}
我的编译器并不喜欢它:
ITalk* lChild = new Child(); // You idiot, Child is an abstract class!
lChild->SayHi();
我无法将 public ITalk
添加到Parent
类,因为“基类'ITalk'已经是'Parent'的基类。”我可以移动 public ITalk
到Parent
类,但在我的特定情况下,这会使很多事情变得复杂。
答案 0 :(得分:4)
不,因为你真正拥有的是两个没有相互了解的基类。
Italk Parent / \ / \ | | +---------+ | Child
如果Parent和Italk有两个名为i的变量,那么就会有两个“i”,ITalk :: i和Parent :: i的实例。要访问它们,您必须完全符合您想要的那个。
方法也是如此,lChild有两个名为SayHi的方法,你需要澄清你在调用SayHi时你指的是哪一个,因为多重继承使它变得模棱两可。
你有父母的SayHi
lChild->Parent::SayHi();
和Italk的SayHi:
lChild->ITalk::SayHi();
后者是纯虚拟的,因为它的摘要需要在Child中本地覆盖。为了满足这个要求,您需要定义
Child::SayHi();
现在,在调用SayHi而不将其作用于类时隐藏Parent :: SayHi():
lChild->SayHi() //parent's now hidden, invoke child's
当然,Child :: SayHi()可以调用Parent :: SayHi():
void Child::SayHi()
{
Parent::SayHi();
}
这将解决您的问题。
答案 1 :(得分:1)
ITalk
包含纯虚函数SayHi()
,因此如果您希望能够实例化一个派生自ITalk
的类,该类必须实现SayHi()
。
class Child : public Parent, public ITalk
{
public:
void SayHi() { std::cout << "Hi!" << std::endl; }
};
或者,Parent
可以继承ITalk
(但不是Child
),您发布的代码也可以使用。
此外,在实现具有虚函数的基类时,必须为这些基类定义虚拟析构函数。所以ITalk应该是:
class ITalk
{
public:
virtual void SayHi() = 0;
virtual ~ITalk() {}
};
如果您不这样做,则以下内容会产生未定义的行为
ITalk* lChild = new Child();
lChild->SayHi();
delete lChild;
答案 2 :(得分:1)
你写这篇文章是不可能完成的。其背后的原因是,每个非静态方法都需要对象(this
)来操作(这里你不使用任何对象的字段或方法,但这没关系),这个对象必须是合适的类型。 Parent::sayHi
期望this
属于Parent
类型,因为ITalk
与Parent
完全无关,Parent::sayHi
和{{1}方法基本上是不兼容的。
C ++具有静态类型系统,因此必须在编译时知道该类型。使用动态类型的语言通常对此类构造不太严格,因为它们可以在函数调用时测试对象是否具有适当的类。
在C ++中,实现此类行为的最简单方法是简单地让ITalk::sayHi
调用Child::sayHi
,因为Child是唯一一个“知道”Parent::sayHi
和{{}的类。 1}}以及它们应该如何相关。
Parent
答案 3 :(得分:0)
尝试使用虚拟继承
class ITalk
{
public:
virtual void SayHi() = 0;
};
class Parent: virtual ITalk
{
public:
void SayHi();
};
class Child : public Parent, public virtual ITalk
{
};
void Parent::SayHi()
{
std::printf("Hi\n");
}