假设我有以下代码:
class Iinterface
{
virtual void abstractFunction()=0;
};
class Derived : public Iinterface
{
void abstractFunction(); // Do I need this line?
};
Derived::abstractFunction()
{
// implementation here
}
如果我没有添加有问题的行,我会收到编译错误,其中abstractFunction
未声明Derived
。我正在使用VS 2008.
我不确定为什么我需要这个特定的行(不要把它与在类声明之外提供的函数定义混淆),只要我继承Iinterface
它应该显而易见我宣布了abstractFunction
。这是Visual Studio的问题还是由c ++标准强制执行?
答案 0 :(得分:8)
如果在所有派生类中隐含了纯虚函数基函数的声明,那么就永远不会有一个派生类相对于纯虚基函数保持抽象。相反,所有派生类都会产生链接器错误。这将是非常反直觉和令人困惑的,它会使语言不那么具有表现力。
此外,它甚至没有意义:派生类是否是抽象的问题必须在编译时知道无处不在。覆盖的实现通常只在一个单独的翻译单元中提供,因此不可能传达这样一个事实,即你实际上意味着该函数被覆盖到程序的其余部分。
答案 1 :(得分:2)
class Derived
class Derived
摘要 Iinterface
和Derived
之间有一个class Intermediate
已覆盖abstractFunction()
;所以现在可以选择class Derived
覆盖相同的修改:使用更改后的问题标题
为什么我必须在派生类中重新声明重写的函数 C ++?
那是因为C ++编译器语法要求必须在class
(或namespace
或文件)中声明class
(或namespace
或文件)的每个成员函数身体。无论是virtual
还是正常的功能
没有有充分理由打破virtual
函数的一致性。
答案 2 :(得分:1)
以=0
结尾的函数称为deleted function
,当您不希望使用某些构造函数的对象(例如unique_ptr
具有已删除的副本时,此功能非常有用构造函数)。
如果删除了virtual
函数,那么按标准,该类将成为抽象类型。因为在大多数情况下,类的原型和类的函数体是在单独的文件中,这意味着除非您在原型中明确地概述了要覆盖已删除的虚函数,否则您不会覆盖已删除的虚函数。编译器不应该只是简单地推断出你想要在一个完全不同的文件中看到实现时将函数放在那里。
请记住,原型/实现思想不是编写代码的唯一方法,您也可以将实现放在类中(如果代码足够小并且您想要内联函数,则可以这样做。)要做到这一点,您需要再次显式覆盖已删除的虚拟功能。因此,无论如何你需要覆盖它,你需要在原型中明确地覆盖它是完全合理的。否则该功能仍然被删除。
举一个具体的例子:假设你有一个List.hpp,List.cpp和main.cpp
在List.hpp中,您有一个抽象类和一个继承自抽象类的常规类。主要是你#include "List.hpp"
而不是List.cpp,对吗?所以编译器没有IDEA该文件中的内容(直到它尝试编译它。)如果你没有覆盖已删除的虚函数,那么编译器认为你只是试图实例化一个抽象类并抛出一个错误。
另一方面,如果您正在编译List.cpp,那么编译器也会抛出错误,这次抱怨您尝试编写的函数实际上没有被定义。因为Base::deletedFunction()
与Derived::deletedFunction()
不同。
答案 3 :(得分:0)
是的,纯虚函数的重点是强制你在派生类中重写它;这个声明必须在c ++
中明确