8

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

考虑这些对象:

struct A
{
    virtual void foo() = 0;
};

struct B
{
    void foo() { /* neat implementation */ }
};

我想知道为什么 --compiler-wise -- 以下对象被认为是抽象的:

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”中是纯的:virtual void A::foo()

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

4

4 回答 4

7

不幸的是,这并不完全符合您的要求。

using指令只是将一些名称带入它使用的范围。virtual方法需要被覆盖,并且仅仅引入名称不被认为是覆盖。

事情的真相是 C++ 不直接支持委托。明确地将名称带入范围只是这种轻微的扭曲。

于 2012-05-10T12:25:14.210 回答
4

struct B正在实现一个恰好被调用foo且不带参数的函数。该功能显然与 绝对没有关系A::foo。因此,当struct C同时派生于Aand时B,它最终继承了:

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

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

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

于 2012-05-10T12:24:53.523 回答
2

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

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

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

于 2012-05-10T12:30:14.877 回答
1

我想这在 C# 中是允许的

C++ 不是 C#。

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

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

于 2012-05-10T12:34:08.700 回答