为什么我必须在重写[C++]时重新声明虚函数

sud*_*03r 27 c++ virtual-functions

#include <iostream>
using namespace std;

class Duck {
public:
        virtual void quack() = 0;
};

class BigDuck : public Duck {
public:
  //  void quack();   (uncommenting will make it compile)

};

void BigDuck::quack(){ cout << "BigDuckDuck::Quack\n"; }

int main() {
        BigDuck b;
        Duck *d = &b;
        d->quack();

}
Run Code Online (Sandbox Code Playgroud)

上面的代码不能编译.但是,当我在子类中声明虚函数时,它编译得很好.

如果编译器已经具有子类将覆盖的函数的签名,那么为什么需要重新声明?

任何见解?

the*_*row 22

需要重新申报,因为:

  • 标准是这样说的.
  • 它通过不爬上层次结构以检查是否存在这样的函数,使编译器的工作更容易.
  • 您可能希望在层次结构中将其声明为较低.
  • 为了实例化该类,编译器必须知道该对象是具体的.

  • 重新声明是**需要**因为,[...]它使编译器的工作更容易 - 哦FFS C++,为什么不只是让每个人都在汇编中编写,它会让编译器的工作变得更容易 (2认同)

Ben*_*ett 11

如果你改变:

virtual void quack() = 0;
Run Code Online (Sandbox Code Playgroud)

virtual void quack();
Run Code Online (Sandbox Code Playgroud)

它将编译而不在HugeDuck中实现quack().

= 0; 在函数声明的最后,本质上是说所有BigDuck都会嘎嘎叫,但它必须由每个派生的duck实现.通过删除= 0; 除非你在HugeDuck中实现嘎嘎,否则BigDuck嘎嘎会被调用.

编辑:澄清= 0; 是说派生类将具有该函数的定义.在你的例子中,它期望HugeDuck定义quack(),但是你已经注释掉了它没有.

作为旁注,既然所有的鸭子都可以嘎嘎叫,那么我们看不到你原来的Duck类应该实现quack()呢?


xto*_*ofl 6

因为C++将'声明'与'多态"分开:任何函数都需要声明编译器,无论它是否为虚拟.

你的例子还不够,它有"抽象类"问题:BigDuck无法实例化,因为它的界面中没有实现quack.

概括问题,我们可以声明基本函数不是纯虚拟的:

class Duck { public: virtual void quack(){} };

class BigDuck : public Duck {}; 
void BigDuck::quack(){ cout << "QUACK!"; }//overrides, but doesn't declare
Run Code Online (Sandbox Code Playgroud)

在这里,编译器会抱怨它有一个BigDuck::quack未声明的符号.这与抽象类或任何东西无关.

(注:GCC说: error: no 'void BigDuck::q()' member function declared in class 'BigDuck' )