虽然其他人正确地谈到了虚方法的性能等问题,但我认为真正的问题在于团队是否了解C ++中虚关键字的定义。
考虑这段代码,输出是什么?
#include <stdio.h>
class A
{
public:
void Foo()
{
printf("A::Foo()\n");
}
};
class B : public A
{
public:
void Foo()
{
printf("B::Foo()\n");
}
};
int main(int argc, char** argv)
{
A* a = new A();
a->Foo();
B* b = new B();
b->Foo();
A* a2 = new B();
a2->Foo();
return 0;
}
这里没有什么惊奇的地方:
A::Foo()
B::Foo()
A::Foo()
因为没有任何东西是虚拟的。如果在 A 和 B 类的 Foo 前面添加 virtual 关键字,我们将得到以下输出:
A::Foo()
B::Foo()
B::Foo()
几乎是每个人都期望的。
现在,你提到有些bug是因为有人忘记添加virtual关键字。那么考虑以下代码(在A类中添加了virtual关键字,但B类没有)。那么输出结果是什么?
#include <stdio.h>
class A
{
public:
virtual void Foo()
{
printf("A::Foo()\n");
}
};
class B : public A
{
public:
void Foo()
{
printf("B::Foo()\n");
}
};
int main(int argc, char** argv)
{
A* a = new A();
a->Foo();
B* b = new B();
b->Foo();
A* a2 = new B();
a2->Foo();
return 0;
}
答案:如果在B中添加了virtual关键字,结果与A::Foo()的结果相同。原因是B::Foo的签名与A::Foo()完全匹配,并且由于A的Foo是虚拟的,所以B的Foo也是虚拟的。
现在考虑B的Foo是虚拟的而A的不是的情况。那么输出结果是什么?在这种情况下,输出结果为:
A::Foo()
B::Foo()
A::Foo()
虚拟关键字在继承层次结构中向下起作用,而不是向上。它从来不会使基类方法成为虚拟的。当多态性开始时,第一次遇到虚拟方法是在继承层次结构中。后面的类没有办法使之前的类有虚拟方法。
不要忘记,虚拟方法意味着该类赋予未来类覆盖/更改其某些行为的能力。
因此,如果您有一个删除虚拟关键字的规则,它可能没有预期的效果。
C++中的虚拟关键字是一个强大的概念。您应该确保团队中的每个成员真正了解这个概念,以便按照设计使用它。