虚函数与const

原创 2007年09月18日 22:56:00

     在网上看到一道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++一个比较搞笑的情况:编译器是尽量防止对只在派生类中存在的函数做虚函数调用的,但是

这里显然突破了这种限制。还有一个例外的地方是明确指出指针在运行时是指向哪个子对象。

 

const虚函数

在C++中,对于两个函数,一个有const修饰,一个没有const修饰,认为这两个函数是不同的函数。 而虚函数的要求是,函数原型相同,函数原型包括:函数返回值、函数名、参数列表、const修饰符。这...
  • pty_2007
  • pty_2007
  • 2013年04月17日 10:14
  • 1000

虚函数与const

     在网上看到一道c++题,解答者说了很多,但感觉没有说明白问题的真正原因。    const的考查。Const这个关键字放在不同的地方将起到不同的作用。题目是这样的:class XBase{p...
  • yagbuchen
  • yagbuchen
  • 2007年09月18日 22:56
  • 1402

virtual IsEmpty() const=0中的const有什么用?

http://blog.csdn.net/xuyongbeijing2008/article/details/8584314 后面加个const 表明该函数不会改名成员函数的值!该函数可以被常量对象...
  • zangchaodotcnatgmail
  • zangchaodotcnatgmail
  • 2015年09月19日 15:19
  • 1234

C++学习之虚函数与纯虚函数

面向对象程序设计(object-oriented programming)的核心思想是数据抽象、继承、动态绑定。通过数据抽象,可以使类的接口与实现分离,使用继承,可以更容易地定义与其他类相似但不完全相...
  • lisong694767315
  • lisong694767315
  • 2014年07月16日 02:05
  • 2183

虚函数后加const

    如果基类的虚函数后加const,派生类相应的函数没有加const,那么虚函数没有起到相应的作用,如果派生类相应的函数也加const,虚函数机制又发挥相应的作用了。但里面的原因是什么呢,也不清楚...
  • wyx819
  • wyx819
  • 2011年05月15日 00:10
  • 566

C++一些注意点之友元函数、虚函数以及const和volatile对象

1.友元函数        定义类时,在类中加上关键字修饰函数,则该函数就能成为该类的友元函数,它可以访问该类的所有成员。关于友元函数需要注意以下几点:      (1)友元函数不是类的成员,不带...
  • luyuncsd123
  • luyuncsd123
  • 2013年06月12日 14:08
  • 2693

趋势一道题目,说说const 重载及虚函数

#include using namespace std; class A{ public: virtual void f(){ cout void f() const {cout ...
  • u014199750
  • u014199750
  • 2014年09月05日 21:57
  • 536

虚函数,多态性,回调函数 简述

0. object based, object oriented. 都是用对象机制对数据进行封装,提高代码复用率,缩知问题空间与解空间之间的距离。 1. 基于对象编程语言 (Object_based...
  • lixiaoguang20
  • lixiaoguang20
  • 2017年03月13日 14:27
  • 352

关于虚函数和多态(很好的解释)

C++:派生类中重定义基类的成员函数与虚函数区别在哪里?
  • foreverhuylee
  • foreverhuylee
  • 2014年07月17日 12:15
  • 2155

C++一些注意点之友元函数、虚函数以及const和volatile对象

1.友元函数        定义类时,在类中加上关键字修饰函数,则该函数就能成为该类的友元函数,它可以访问该类的所有成员。关于友元函数需要注意以下几点:      (1)友元函数不是类的成员,不带...
  • u010064842
  • u010064842
  • 2013年06月10日 21:19
  • 2116
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:虚函数与const
举报原因:
原因补充:

(最多只允许输入30个字)