为什么我不能使用继承来实现C++中的接口?

Why can't I use inheritance to implement an interface in C++?

本文关键字:C++ 接口 实现 不能 继承 为什么      更新时间:2023-10-16

可能的重复项:
在父类中实现抽象类
成员 为什么C++不允许基类实现派生类的继承接口?

考虑这些对象:

struct A
{
    virtual void foo() = 0;
};
struct B
{
    void foo() { /* neat implementation */ }
};

我想知道为什么 --编译器明智 - 以下对象被认为是抽象的:

struct C : B, A
{
    using B::foo; // I tried my best to make the compiler happy
};

编译器不允许我这样做:

A* a = new C;

Visual Studio 2010 说:

'C' : 由于以下成员而无法实例化抽象类: 'void A::foo(void)' : 是抽象的 : 参见 'A::foo' 的声明

G++ 4.6.3 说:

无法分配抽象类型"C"的对象,因为以下虚函数在"C"中是纯的:虚拟空 A::foo()

我想这在 C# 中是允许的,但我不知道所涉及的 mecanism——我只是好奇。

不幸的是,这并不能完全满足您的要求。

using指令只是将一些名称纳入其使用的范围。 virtual方法都需要重写,并且仅引入名称不被视为重写。

事情的真相是,C++并不直接支持授权。将名称明确纳入范围只是略有转折。

struct B正在实现一个恰好被称为foo并且不带参数的函数。该功能显然与A::foo完全无关。所以当struct C同时派生自AB时,它最终继承了:

  • A::foo提供实现的责任
  • A::foo具有相同名称和签名的方法B::foo,但与它没有任何关系

我认为问题很明显。您正在尝试将A用作 C# interface 的等效项,但无法在C++中表达该概念。

现在 using 指令在这里也无济于事,因为它所做的只是将B::foo带入C的范围,这意味着它告诉编译器它应该考虑B::foo作为解析名称的候选者foo当后者在类 C 中遇到时。不幸的是,这也与实现纯虚拟方法的责任无关。

要解决这个问题,你需要在 C 中实现你自己的foo()并显式调用 B 函数——有效地将 A::foo 转发到 C 中的 B::foo:

struct C : B, A
{
  virtual void foo() {
    // Override A::foo by forwarding to B::foo:
    B::foo();
  }
};

这在某种程度上是有意义的——A::foo() 和 B::foo() 之间没有内在的关系——你必须在 C 中明确地建立一个。

我想这在 C# 中是允许

C++不是 C#。

virtual void foo()void foo()是两种不同的方法。

当您从 A 和 B 派生时,您可以访问两种方法:virtual A::foo 和非虚拟B::foovirtual A::foo是抽象的。因此编译器错误。