为什么我需要在子类中重新声明"虚拟"方法?[C++/多态性]
Why do I need to re-declare `virtual` methods in my Sub-Class? [C++ / Polymorphism]
有人能解释一下,如果我们有一个具有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
也将是一个抽象类,并且函数可以在进一步的派生类中定义。也许下降了好几个层次。
相关文章:
- 为不同配置设置MSVC_RUNTIME_LIBRARY的正确方法是什么
- 通过方法访问结构
- 最小硬币更换问题(自上而下方法)
- C++为构建时间获取QDateTime的可靠方法
- 在C#中处理C++指针而不使用unsafe的最佳方法
- 处理多个异常集合的C++方法
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗
- 有什么方法可以遍历结构吗
- 当类在C++中定义时,有什么方法可以"register"类吗?
- 在C++中,将大的无符号浮点数四舍五入为整数的最佳方法是什么
- 实现无开销push_back的最佳方法是什么
- 使用std::函数映射对象方法
- 有符号的int和int-有没有一种方法可以在C++中区分它们
- C++从另一个类访问公共静态向量的正确方法是什么
- C++优先级队列,按对象的唯一指针的特定方法升序排列
- 没有为自己的结构调用列表推回方法
- 有没有什么方法可以使用一个函数中定义的常量变量,也可以由c++中同一程序中的其他函数使用
- 在类定义之后定义一个私有方法
- 枚举环境变量的惯用C++14/C++17方法
- 初始化具有非默认构造函数的std::数组项的更好方法