为什么我需要在子类中重新声明"虚拟"方法?[C++/多态性]

Why do I need to re-declare `virtual` methods in my Sub-Class? [C++ / Polymorphism]

本文关键字:quot 方法 虚拟 多态性 C++ 声明 子类 新声明 为什么      更新时间:2023-10-16

有人能解释一下,如果我们有一个具有virtual成员函数的抽象类,为什么我们需要在我们的子类中再次声明它吗?例如,参见下面的示例

抽象类

.h文件

#ifndef ALGORITHM_H
#define ALGORITHM_H
#include <vector>
#include "Event.h"
using std::vector;
class Algorithm{
protected:
vector<Event>* dataset;
public:
Algorithm(vector<Event>& dataset);
virtual ~Algorithm();
virtual void run() = 0;
};
#endif

.cpp文件

#include "../include/Algorithm.h"
Algorithm::Algorithm(vector<Event>& dataset):dataset(&dataset){}
Algorithm::~Algorithm(){}

假设声明了纯虚拟函数run,通过扩展这个类,我的期望是它只需要实现。然而,它仍然需要在扩展这个抽象类的类中进行声明。

子类

.h文件

#ifndef SELECT_ALGORITHM_RANDOM_H
#define SELECT_ALGORITHM_RANDOM_H
#include "Algorithm.h"
class SelectAlgorithmRandom : public Algorithm{
public:
SelectAlgorithmRandom(vector<Event>& dataset);
~SelectAlgorithmRandom();
void run(); // <-- why do I need this here, and doesn't it defy the purpose of me declaring virtual `run` function in `Algorithm`? 
};
#endif

.cpp文件

#include "../include/SelectAlgorithmRandom.h"
SelectAlgorithmRandom::SelectAlgorithmRandom(vector<Event>& dataset):Algorithm(dataset){}
SelectAlgorithmRandom::~SelectAlgorithmRandom(){}
void SelectAlgorithmRandom::run(){
//  TODO
}

您必须添加声明,因为C++标准要求在类定义本身中声明类的每个成员:

[class.mem]/1:

类定义中的成员规范声明了该类的完整成员集;不能在其他位置添加任何成员。

成员同时引用函数和数据。Algorithm中有一个纯虚拟函数,这并不意味着SelectAlgorithmRandom也会定义它。类可以通过继承层次结构的几个层保持抽象。

要定义run函数,必须在类定义中明确指定该意图。

顺便说一句,在现代C++中,最好声明函数意味着为覆盖:

void run() override;

这样,编译器会根据基类版本的定义对其进行检查,以确保您真正覆盖了基类中的某些内容,而不是添加重载或一些无关的函数。

简而言之,如果要实现polymorphism,请使用虚拟方法和指向基类的指针。

class A{
public:
virtual void F(){std::cout << "Base A::Foo()" << std::endl;}
};
class B : public A{
public:
void F(){std::cout << "B::Foo()" << std::endl;}
};

现在主要是:

int main(){
A* ptrA = new B;
ptrA->Foo();
return 0;
}

正如您在上面看到的,方法Foo的调用取决于ptrA指向的对象类型

  • 方法重写需要在派生类中重新声明虚拟方法

您必须在SelectAlgorithmRandom的声明中声明run()函数,以表明您实际上打算为该类定义它。

如果不是,SelectAlgorithmRandom也将是一个抽象类,并且函数可以在进一步的派生类中定义。也许下降了好几个层次。