3

这可能以前已经回答过,但我找不到单词。

我试图将我的头脑围绕在继承中C++,但来自C#我似乎无法理解以下案例背后的原因:

Foo.h

class Foo {
    virtual void DoSomething();
}

class Bar : Foo { }

Bar.cpp

#include "Foo.h"    
void Bar::DoSomething() 
{
    //Compiler error C2509 - member function not declared in 'Bar'
}

既然DoSomething是一个虚函数,难道不应该将它隐式声明为 的一部分Bar吗?

如果我有很多不同的类继承自Foo,我真的需要DoSomething在每个类中显式声明吗?

C++处理这种情况还有哪些其他构造?

4

3 回答 3

10

C++ 语言建立在与 C 相同的独立翻译原则上。这意味着 C++ 程序中的所有翻译单元应该可以完全独立地编译。当编译器本身已经完成工作时,它们稍后会链接到最终程序中。

对于类,为了能够独立编译每个翻译单元,编译器必须能够通过单独查看类的定义(即通常放置在头文件。在编译一个翻译单元时,编译器必须知道它DoSomething被覆盖Bar并且定义void Bar::DoSomething()存在于某处,在某个其他翻译单元中。为了实现这一点,类定义必须包含所有类成员函数的声明。

我完全不清楚您对“纯虚函数”的推理。首先,它在您的代码示例中并不纯粹(显然您只是忘记了该= 0部分)。其次,仅仅因为基类函数是纯函数并不意味着派生类函数应该是非纯函数。很有可能它Bar也应该是一个抽象类。这是你的意图问题,编译器不知道。

于 2013-10-01T18:42:58.880 回答
3

的定义Bar是大多数代码都会知道的。其他翻译单元将看不到“Bar.cpp”,但仍需要生成正确的Bar实例内存表示,包括Bar的 vtable。这意味着他们需要知道 Bar 是否真的被覆盖Foo::DoSomething,因为内存中的表示会有所不同。

于 2013-10-01T18:42:46.247 回答
2

是的,您确实需要显式声明此方法。来自 C#,您会注意到 C++ 在很多事情上都不会“握住您的手”。我不是那种侮辱性的意思,但是 C++ 强迫你在你所做的每一件事上都非常明确。

于 2013-10-01T18:37:09.940 回答