在网上看到一道c++题,解答者说了很多,但感觉没有说明白问题的真正原因。
const的考查。
Const这个关键字放在不同的地方将起到不同的作用。
题目是这样的:
class XBase
{
public:
virtual void play()const
{
cout<<"base play"<<endl;
}
};
class XWind:public XBase
{
public:
void play()
{
cout<<"wind play"<<endl;
}
};
class XBrass:public XWind
{
public:
void play()
{
cout<<"brass play"<<endl;
}
};
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 play
brass play
回来我运行一遍,发现错了:
是
base play
base play
但是把基类改为:
class XBase
{
public:
const virtual void play()
{
cout<<"base play"<<endl;
}
};
派生类作相应的改动:
class XWind:public XBase
{
public:
const void play()
{
cout<<"wind play"<<endl;
}
};
class XBrass:public XWind
{
public:
const void play()
{
cout<<"brass play"<<endl;
}
};
则运行结果为:
wind play
brass play
原来Const这个关键字放在不同的地方将起到不同的作用。
大家可以试一下,顺便说一下原理。
解答者:
不论派生类如何修改只要与基类不符就选择调用基类class XBase
virtual void play()const; // 原型:void play() cont
class XWind:public XBase // 从XBase派生
void play(); // 不符合基函数play,调用基play
XBrass:public XWind // 从XWind派生
void play(); // 符合函数XWind::play,但因为
// XWind::play调用XBase::play
// 因此XBrass::play调用XBase::play
你可以试试这样修改,你就会明白
XBase
virtual void play() const;// 原型
XWind : public XBase
void play() cont; // 符合,调用自己的play
XBrass : public XWind
void play(); // 与XWind::play不符,调用XWind::play
---------------------------------------------------------------
XBase
virtual void play() const;// 原型
XWind : public XBase
void play(); // 不符合,调用XBase::play
XBrass : public XWind
void play() const; // 与XWind::play不符,往下一级寻找play
// 与XBase::play相同,调用自己的play
----------------------------
两次的输出结果为:
1.wind play
wind play
2.base play
brass play
解答者说的是正确的。 不过具体原因,自己写个c++例子,查它的汇编代码就明白了。
比如 XBase 的虚函数表里有一个函数指针:
_XBase_play
XWind的虚函数表里有两项:
_XBase_play
_XWind_play
如果通过XBasePtr->play来调用,编译器是按虚函数表里的偏移量来call的,这时候会调用到base的play函数。
如果通过XWindPtr->play来调用,会调用到XWind的play函数。
如果const修饰一致,那么XWind的虚函数表里将只有一项:
_XWind_play
这个问题反应了c++一个比较搞笑的情况:编译器是尽量防止对只在派生类中存在的函数做虚函数调用的,但是
这里显然突破了这种限制。还有一个例外的地方是明确指出指针在运行时是指向哪个子对象。