在父类中实现抽象类成员

时间:2011-08-23 21:07:30

标签: c++ inheritance abstract-class

是否可以实现一个抽象基类,其成员继承自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 ITalkParent类,但在我的特定情况下,这会使很多事情变得复杂。

4 个答案:

答案 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类型,因为ITalkParent完全无关,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");
}