C++ Virtual Void vs no virtual
本问题已经有最佳答案,请猛点这里访问。
我对虚拟函数感到困惑。我被告知父类中的虚拟意味着我可以在子类中重写它。但是,如果在父类中省略了虚拟,我仍然可以重写它。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | #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(); } |
您可以重写所讨论的方法,并在理想情况下使用
1 2 3 4 5 6 7 8 9 10 11 | class Enemy { public: virtual ~Enemy() = default; /* Don't forget... or non-virtual protected. */ virtual void attack() {} }; class Minion : public Enemy { public: void attack() override {} }; |
您的困惑可能源于这样一个事实:您同样可以很好地隐藏基类方法。
1 2 3 4 5 6 7 8 9 10 | class Enemy { public: virtual ~Enemy() = default; void attack() {} }; class Minion : public Enemy { public: void attack() {} }; |
这不仅做了一些不同的事情,而且是一个非常糟糕的命名的例子,因为它让读者感到困惑:在类层次结构的上下文中,具有相同签名的相同成员函数名不可避免地与被重写的方法相关联。
如果函数是虚拟的,那么调用将在运行时通过vtable动态调度到派生类型提供的实现,而如果没有,编译器将在编译时查看对象并选择静态类型的类方法。如果您有指向基类的指针,这意味着使用了基本实现,如果函数不是虚拟的:
将打印"攻击敌人!"如果
如果要强制派生类重写基类方法,还可以使用
您没有重写它,只是添加了另一个具有相同签名的方法。
1 2 3 4 5 | Enemy* enemy = new Minion(); enemy->attack(); delete enemy; |
如果这调用了