继承、纯虚函数和非内联成员函数定义 [已关闭]

Inheritance, pure virtual functions and non-inline member function definitions [closed]

提问人:J Collins 提问时间:3/12/2014 最后编辑:J Collins 更新时间:3/12/2014 访问量:172

问:


这个问题似乎偏离了主题,因为它缺乏足够的信息来诊断问题。更详细地描述您的问题,或在问题本身中包含一个最小的示例

9年前关闭。

我已将我的问题归结为以下代码,全部在一个*.cpp文件中:

class A {
public:
    A() {};

    int PerformAction() {
        return Action();
    }

protected:
    virtual int Action();
}

class B: public A {
protected:
    int Action();
}

int B::Action() {
   return 4;
}

int main() {
    B newB;
    newB.PerformAction();
};

前面的代码抛出一个 .将 的定义更改为:Unresolved external symbol error on B::Action()a::Action()

virtual int Action() = 0;

相反,在 main 函数中使用编译器错误时会产生编译器错误。我看到的所有答案都与将代码分布在多个文件中有关,但这都发生在一个源文件中。我想这与在类定义之外的实现有关,但看不出它会导致任何错误的任何原因。Cannot instantiate abstract classBAction()B

C++ 继承未 解析-外部 纯-虚拟

评论

2赞 Mike Seymour 3/12/2014
这显然不是您正在编译的代码 - 缺少分号并尝试调用受保护的函数将在您报告的链接器错误之前给出编译器错误。一旦我修复了这些错误,并按照您的描述使函数纯虚拟,就没有错误了:ideone.com/IS7PJj
0赞 Mike Seymour 3/12/2014
另外,请不要在发布的代码中添加行号;为了测试它而必须移除它们是一种痛苦。
0赞 Mike Seymour 3/12/2014
另外,必须返回.mainint
1赞 Mike Seymour 3/12/2014
为了了解出现错误的原因,我们需要演示错误的代码。此代码具有不同的错误(缺少分号和错误的类型),并在修复这些错误后干净地编译。无法知道您的代码可能出了什么问题。据推测,它正在做一些试图实例化的事情,但除此之外我无法猜测。mainA
1赞 Jonathan Wakely 3/12/2014
因此,将其简化为表现出相同错误的代码。上面的代码甚至没有表现出您声称的错误。至少,尝试编译/链接/运行您在此处发布的代码,并报告该实际代码中的错误,而不是您未向我们展示的其他代码。

答:

2赞 Mike Seymour 3/12/2014 #1

前面的代码在 上抛出 Unresolved external symbol 错误。B::Action()

事实上,必须定义所有非纯虚函数,以便它们的地址可以存储在类的虚函数表中。

而是产生 Cannot instantiate abstract class compiler 错误

不,它没有:http://ideone.com/IS7PJj

如果你尝试直接实例化,或者一个没有覆盖纯虚函数的子类,你会得到这个错误。 确实覆盖了它,因此不是抽象的。AB

可能,您的真实类具有不正确的签名,因此它实际上不会覆盖 中声明的签名。在 C++11 中,您可以将说明符添加到 中的说明符,以便在这种情况下获得更有用的错误消息。BActionAoverrideB

我想这与在类定义之外的实现有关BAction()B

不,这应该不是问题,只要函数只有一个定义。

评论

0赞 J Collins 3/12/2014
我想这是我的困惑,在我的代码 B 中肯定实现了 Action(),(或者它在现实世界中的等价物),尽管我仍然收到该错误。我相信你说的是,在其他地方寻找这个问题,因为它不是特定结构和用法选择的功能。
0赞 Lightness Races in Orbit 3/12/2014
Indeed, all non-pure virtual functions must be defined, so that their address can be stored in the virtual function table for the class.而且,更抽象地说,这样就可以调用它们!
0赞 Mike Seymour 3/12/2014
@LightnessRacesinOrbit:是的;但是(与大多数函数不同)即使没有调用它们,也必须定义它们。
2赞 Ben Voigt 3/12/2014 #2

总而言之,您的错误消息表明 和 之间的签名不匹配,因此不会成为覆盖。签名必须完全匹配(包括 的 cv-qualification),但允许返回类型协方差。A::ActionB::ActionB::Actionthis

并且必须是.如果签名匹配,则为隐式匹配,除非它是模板。模板无法覆盖。B::Actionvirtual

如果您有 C++11 编译器,我建议使用 关键字,使签名不匹配成为编译错误。override

评论

0赞 J Collins 3/12/2014
很漂亮,这是我需要的提示。我正在使用 VC++ Express 2008,不确定其中的编译器是什么。问题是一些不必要的 template<typename 调用......>函数实现,使它们不能真正覆盖。
0赞 Ben Voigt 3/12/2014
@JCollins:模板函数从来都不是虚拟的,所以这听起来像是你的问题。
0赞 J Collins 3/12/2014
这就是我正在学习的。幸运的是,问题得到了解决,我现在可以很好地编译了。干杯。