Overriding rules in C++
从Java的角度来看,我惊讶地发现,您只能重写具有虚拟关键字的基本方法。在爪哇中,使用最后一个关键字声明无法重写的方法。
我脑子里有个想法,就是你很少想禁止凌驾于世,这样别人就可以根据自己的情况来扩展你的课程。
所以在C++中,如果你觉得某人可能想在某个阶段继承你的班级(也许几年后有人认为这是一个很酷的想法),你会让你的方法都是虚拟的吗?
或者是有一些重要的原因,想要禁止在C++中,我没有意识到这一点?
作为参考,这是我对每种语言所做的实验:
爪哇
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
C++
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | class Base { public: Base(void); ~Base(void); virtual void doSomething(); }; void Base::doSomething(){ std::cout <<"I'm doing the base thing " << std::endl; } class Derived : public Base { public: Derived(void); ~Derived(void); void doSomething(); }; void Derived::doSomething(){ std::cout <<"I'm doing the dervied thing" << std::endl; } int main(void){ Base * object = new Derived; object->doSomething(); return 0; } |
达菲莫和艾尔斯正把你带向正确的方向。我只是想对你说的一件事发表评论:
So in C++ if you feel that someone might want to at some stage inherit
from your class (maybe years later someone thinks its a cool idea) do
you make all your methods virtual?
从软件工程的角度来看:如果您没有立即使用继承,也没有使用接口,那么我不建议将方法声明为虚拟的。
虚拟方法带来了非常轻微的性能下降。对于非关键代码路径,性能影响可能可以忽略不计。但是对于经常被调用的类方法,它可以加起来。编译器不能做太多的内联和直接链接。相反,必须在运行时在v-table数组中查找要调用的虚拟方法。
当我的编码团队中有人开始与"稍后可能会有人想要…"进行设计对话时,我的"未来校对"反模式警报就会响起。设计可扩展性是一回事,但"面向未来的特性"应该推迟到那时。
此外,多年后那个认为这是一个很酷的想法的人,让他自己把类方法转换成虚拟的。不管怎么说,到那时你将进入更大的项目。:)
是的,你必须使你所有的方法都是虚拟的。
Java认为默认情况下一切都是公平的游戏,而禁止它需要采取行动。C++和C语言的观点截然相反。
是的,在C++中,一个类方法只能是EDOCX1×0,如果它在基类中被标记为EDCOX1×1。
如果您的类是为继承而创建的,并且您的类方法打算为基和派生提供不同的行为,那么将该方法标记为
良好阅读:
何时将C++中的函数标记为虚拟?
来自于虚函数缺省的语言的程序员往往会惊讶于C++具有逆向选择的默认值,即非虚拟是默认值。但是,请注意,[具体]虚拟函数的契约很难记录和测试,因为实际上涉及两个不同的契约:
只记录其中的一个并不能真正减少它,因为另一半根本不清楚。这也意味着您不能从具体的实现中瞥一眼实际的合同是什么(假设您处于一种不那么不典型的情况下,文档是由源提供的)。
即使没有
以这个小程序为例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | #include <iostream> struct A { void m() { std::cout <<"A "; } virtual void n() { std::cout <<"A "; } }; struct B : public A { void m() { std::cout <<"B "; } virtual void n() { std::cout <<"B "; } }; int main() { A a; a.m(); a.n(); B b; b.m(); b.n(); A &c = b; c.m(); c.n(); } |
程序输出为:
1 2 3 4 5 6 | A A B B A B |
如您所见,方法