C++虚拟虚空与无虚拟
C++ Virtual Void vs no virtual
我对虚拟函数感到困惑。有人告诉我,父类中的虚拟意味着我可以在子类中覆盖它。然而,如果我省略了父类中的虚拟,我仍然可以覆盖它
#include <iostream>
using namespace std;
class Enemy{
public:
//if I remove virtual, it still gets overriden in child class
virtual void attack(){
cout << "Attack Enemy!" << endl;
}
};
class Minion : public Enemy {
public:
void attack(){
cout << "Attack Minon!" << endl;
}
};
int main() {
Minion m;
m.attack();
}
如果函数是虚拟的,则在运行时通过vtable将调用动态调度到派生类型提供的实现,而如果没有,则编译器在编译时查看对象并选择静态类型的类方法。如果你有一个指向基类的指针,这意味着使用了基本实现,如果函数不是虚拟的:
Enemy *e = new Minion(); e->attack();
如果attack
不是虚拟的,将打印"攻击敌人!"。当使用虚拟函数时,编译器将插入一些逻辑以在运行时查找正确的实现,并且当执行e->attack()
时,在e
指向的对象指针的vtable中查找该实现,发现Minion
覆盖attack
,从而打印"Attack Minion!"。
如果你想强制你的派生类覆盖基类方法,你也可以通过使用使函数完全虚拟
virtual void attack() = 0;
您可以重写有问题的方法,理想情况下使用override
关键字声明该方法,以允许编译器在您没有重写任何内容时进行抱怨。
class Enemy {
public:
virtual ~Enemy() = default; /* Don't forget... or non-virtual protected. */
virtual void attack() {}
};
class Minion : public Enemy {
public:
void attack() override {}
};
您的困惑可能源于这样一个事实,即您同样可以很好地隐藏基类方法。
class Enemy {
public:
virtual ~Enemy() = default;
void attack() {}
};
class Minion : public Enemy {
public:
void attack() {}
};
这不仅起到了不同的作用,而且还将成为命名异常糟糕的一个例子,因为这让读者感到困惑:在类层次结构的上下文中,具有相同签名的相等成员函数名不可避免地与重写方法相关联。
您还没有覆盖它,只是添加了另一个具有相同签名的方法。
Enemy* enemy = new Minion();
enemy->attack();
delete enemy;
如果this调用Minion
中的代码,那么您做得对。如果它调用Enemy
中的代码,则表明您做错了什么。你需要virtual
来做正确的事情。
相关文章:
- 虚拟决赛作为安全
- PowerPC ppc64le上的Gcc Woverloaded虚拟错误
- 如何在C++中获得"静态纯虚拟"功能?
- C++无法定义虚拟函数 OUTER 类和头文件
- 用常见虚拟函数实现的任意组合来实现派生类的正确方法是什么
- 在模板基类中为继承类中的可选重写生成虚拟方法
- 尝试将unique_ptrs推送到向量时使用纯虚拟函数错误
- 有没有比在库中添加一个并非由所有派生类实现的新虚拟函数更好的设计实践
- 大小虚拟继承中的派生类
- 链接器找不到在虚拟类 c++ 中访问的静态字段的符号
- 使用 C++ 和 i2c 工具从虚拟 i2c 写入和读取
- 重载 -> shared_ptr 个实例中的箭头运算符<interface>,接口中没有纯虚拟析构函数
- 如果整个应用程序是虚拟映射的,为什么 new 会进行系统调用?
- 跨 DLL 边界访问虚拟方法是否安全/可能?
- std::is_trivially_copyable_v 关于虚拟功能
- 删除C++继承中虚拟类成员的代码重复
- 子类地址等于虚拟基类地址?
- 当覆盖存在时调用基本虚拟"binded to object"函数
- 用于创建/注册虚拟存储设备的 IOKit 驱动程序
- 是否可以使用基类非虚拟方法中的派生类虚拟方法?