在父类中实现抽象类成员 < > >可以在C++中使用继承自另一父类的成员来实现抽象基类吗?< /强>
它在C#中工作,所以我试着用C++:在父类中实现抽象类成员 < > >可以在C++中使用继承自另一父类的成员来实现抽象基类吗?< /强> ,c++,inheritance,abstract-class,C++,Inheritance,Abstract Class,它在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
// 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
类,但在我的特定场景中,这会使很多事情变得复杂。ITalk
包含纯虚拟函数SayHi()
,因此如果您希望能够实例化从ITalk
派生的类,那么该类必须实现SayHi()
如果您不这样做,下面将生成未定义的行为
ITalk* lChild = new Child();
lChild->SayHi();
delete lChild;
不,因为你真正拥有的是两个基类,彼此都不了解 Italk Parent / \ / \ | | +---------+ | Child 还有Italk的SayHi:
lChild->ITalk::SayHi();
后者是纯虚拟的,因为它的抽象需要在Child中本地重写。要满足这一点,您需要定义
Child::SayHi();
调用SayHi时,它现在将隐藏Parent::SayHi(),而不将其范围限定到类:
lChild->SayHi() //parent's now hidden, invoke child's
当然,Child::SayHi()可以调用Parent::SayHi():
这将解决您的问题。尝试使用虚拟继承
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");
}
这不可能像你写的那样完成。其背后的原因是,每个非静态方法都需要对象(
this
)来操作(这里您不使用对象的任何字段或方法,但这并不重要),并且该对象必须是适当的类型Parent::sayHi
期望this
属于Parent
类型,并且由于ITalk
与Parent
根本不相关,Parent::sayHi
和ITalk::sayHi
方法基本上是不兼容的
C++具有静态类型系统,因此必须在编译时知道类型。使用动态类型的语言通常对这种结构不太严格,因为它们可以在函数调用时测试对象是否属于适当的类
<>在C++中,实现这种行为的最简单的方法是简单地制作<代码>子::SayHi/Cux>调用<代码>父::SayHi/Cuth>,因为子是唯一知道“<代码>父/代码>和<代码> ITALK >的类,它们应该如何关联。
class Child : public Parent, public ITalk
{
virtual void sayHi(){ Parent::sayHi(); }
};
所以不
子类
无法继承它要用于实现ITalk
?@emddudley Yep的成员,无法继承。DougT.解释了为什么这会使编译器更清楚地看到函数。如果说编译器在查找ITalk::SayHi()
的重写实现时只查看本地类,而不搜索继承树,这是否正确?是的。当实例化一个对象时,编译器会根据您正在实例化的对象进行查找,并确保它正上方的任何纯虚拟对象都已在本地实例化。
lChild->SayHi() //parent's now hidden, invoke child's
void Child::SayHi()
{
Parent::SayHi();
}
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");
}
class Child : public Parent, public ITalk
{
virtual void sayHi(){ Parent::sayHi(); }
};