-
虚函数与const
Const这个关键字放在不同的地方将起到不同的作用。题目是这样的:class XBase{public: virtual void play()const { cout<<"base play"<}};class XWind:public XBase{public: void play() { cout<<"wind play"< }};class XBrass:public XWind{public: void play() { cout<<"brass play"< }};void Tune(XBase& b){ b.play();}void main(){ XBase* base[] = {new XWind(),new XBrass()};for(int i = 0;i < 2;i++)
{ Tune(*base[i]); }}问这段代码的运行结果:开始我以为很容易:不就是:wind playbrass play回来我运行一遍,发现错了:是base playbase play但是把基类改为:class XBase{public: const virtual void play() { cout<<"base play"<}};派生类作相应的改动:class XWind:public XBase{public: const void play() { cout<<"wind play"< }};class XBrass:public XWind{public:const void play() { cout<<"brass play"< }};则运行结果为:wind playbrass play原来Const这个关键字放在不同的地方将起到不同的作用。大家可以试一下,顺便说一下原理。解答者: 不论派生类如何修改只要与基类不符就选择调用基类class XBasevirtual void play()const; // 原型:void play() contclass XWind:public XBase // 从XBase派生void play(); // 不符合基函数play,调用基playXBrass:public XWind // 从XWind派生void play(); // 符合函数XWind::play,但因为 // XWind::play调用XBase::play // 因此XBrass::play调用XBase::play你可以试试这样修改,你就会明白XBasevirtual void play() const;// 原型XWind : public XBasevoid play() cont; // 符合,调用自己的playXBrass : public XWindvoid play(); // 与XWind::play不符,调用XWind::play---------------------------------------------------------------XBasevirtual void play() const;// 原型XWind : public XBasevoid play(); // 不符合,调用XBase::playXBrass : public XWindvoid play() const; // 与XWind::play不符,往下一级寻找play // 与XBase::play相同,调用自己的play----------------------------两次的输出结果为:1.wind play wind play2.base play brass play解答者说的是正确的。 不过具体原因,自己写个c++例子,查它的汇编代码就明白了。比如 XBase 的虚函数表里有一个函数指针:_XBase_playXWind的虚函数表里有两项:_XBase_play_XWind_play如果通过XBasePtr->play来调用,编译器是按虚函数表里的偏移量来call的,这时候会调用到base的play函数。如果通过XWindPtr->play来调用,会调用到XWind的play函数。如果const修饰一致,那么XWind的虚函数表里将只有一项:_XWind_play这个问题反应了c++一个比较搞笑的情况:编译器是尽量防止对只在派生类中存在的函数做虚函数调用的,但是这里显然突破了这种限制。还有一个例外的地方是明确指出指针在运行时是指向哪个子对象。 2010/11/5 11:04:02
举报不良信息