关闭

避免对派生的非虚函数进行重定义

发表于:2013-1-30 09:45

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:驿落黄昏    来源:51Testing软件测试网采编

  今天无意中发现一个关于C++基础的问题,当时愣是没理解是什么原因,现在搞明白了,就写下来了。先看小程序,先实践再理论吧,要不大家就睡着了。

  1. #include <iostream> 
  2. using namespace std; 
  3. class Base 
  4. public
  5.       virtual void funtion(int arg = 1){cout<<arg<<endl;}       
  6. }; 
  7. class Derive : public Base 
  8. public
  9.       virtual void funtion(){cout<<"Derive"<<endl;} 
  10.       virtual void funtion(int arg){cout<<"Derive"<<arg<<endl;}       
  11. }; 
  12. int main(int argc, char *argv[]) 
  13.     Base* obj = new Derive(); 
  14.     obj->funtion(); 
  15.     system("pause"); 
  16.     return 0;     
  17. }

  上面的程序会出现什么结果呢?我想会有很多人看到这个地方就会怀疑我程序的正确性了,大呼“你的程序是错的”,但真的错吗?我们可以先执行下程序看下结果。很明显,结果是调用了子类的函数,并且子类中arg参数的值是父类中的值1,运行结果为“Derive 1”。

  下面我就解释下这种结果的原因,首先我先要说下对象的两种类型:动态类型和静态类型。

  静态类型:指针或者是引用声明时的类型。

  动态类型:由他实际指向的类型确定。

  例如:

  1. Base *pgo=   //pgo静态类型是Base * 
  2. new Derive; //动态类型是Derive * 
  3. Asterioid *pa = new Asterioid; //pa的静态类型是 Asterioid * 
  4. //动态类型也是 Asterioid * 
  5. pgo = pa; //pgo静态类型总指向Base * 
  6. //动态类型指向了 Asterioid * 
  7. Base &rgo = *pa; //rgo的静态类型是Base 
  8. //动态类型是 Asterioid

  虚函数是动态绑定的,而默认参数值是静态绑定的。运行时效率。如果默认参数值是动态绑定的话,那么编译器必须提供一整套方案,为运行时的虚函数参数确定恰当的默认值。而这样做,比起C++当前使用的编译时决定机制而言,将会更复杂、更慢。鱼和熊掌不可兼得,C++将设计的中心倾向了速度和简洁,你在享受效率的快感的同时,如果你忽略本条目的建议,你就会陷入困惑。

  其实对于这个问题在[Effective C++第3版]中也有提到,其第36条:避免对派生的非虚函数进行重定义。下面看下书中的描述:

  现在考虑以下的层次结构:B是一个基类,D是由B的公有继承类,B类中定义了一个公有成员函数mf,由于这里mf的参数和返回值不是讨论的重点,因此假设mf是无参数无返回值的函数。也就是说:

  1. class B { 
  2. public
  3.   void mf(); 
  4. }; 
  5. class D: public B {  }; 
  6. 即使不知道B、D、mf的任何信息,让我们声明一个D的对象x: 
  7. D x;                           // x 是D类型的对象 
  8. B *pB = &x;                       // 指向x的指针 
  9. pB->mf();                         // 通过指针调用mf函数 
  10. D *pD = &x;                       // 指向x的指针 
  11. pD->mf();                         // 通过指针调用mf函数

  在这里,如果告诉你pD->mf()与pB->mf()可能拥有不同的行为,你一定会感到意外。这也难怪:因为两次都是在调用x对象的成员函数mf,因为两种情况下都是用了同一函数和同一对象,mf()理所应当应该有一致的行为。难道不是吗?

21/212>
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号