Effective C++ Item 36 & 37 关于继承来的非虚函数和默认参数

转自:http://www.cppblog.com/note-of-justin/archive/2010/03/04/106351.aspx

条例36很简短,切勿重写继承来的非虚函数。看了看也就一句话能说明白的事:对于父类的非虚函数,子类老老实实继承即可,不要重写覆盖。道理确是很简单,如果是可以重新定义的函数,人家自然会用虚函数;如果用的是非虚函数,明摆着就是不让你乱动嘛@#¥%

接下来的37也不难理解:不要试图修改继承来的虚函数的默认参数。原因嘛,要记录一下,大师说了:

  • 虚函数是动态绑定的,或者说是执行期确定的。
    函数(包括虚函数)的默认参数是静态绑定的,或者说是编译期确定的。
  • 所以我们可以写出和父类不一样的虚函数实现,
    但是不能指定另外一个和父类函数默认参数不一样的默认参数。

有点拗口,没时间编例子了,就还是看代码吧:

class  AClass
{
   
public :
      
virtual   void  func(  int  param  =   123  )
      
{
         
// ..
      }

   
// ..
}
;

class  AClassDerived :  public  AClass
{
   
public :
      
//  problematic overwriting the default parameter..
       virtual   void  func(  int  param  =   456  )
      
{
         
// ..
      }

   
// ..
}
;

int  main()
{
   AClass 
*  pA  =   new  AClassDerived;
   pA
-> func();
   
// ..
}


在上面的代码中,由于函数默认参数的静态绑定特性,pA->func()执行时param事实上被赋予了123,而非子类中期望的456,虽然接下来执行的是子类的函数实现……
为什么函数默认参数不能是动态绑定的呢?因为C++考虑到执行效率和复杂性方面的代价,规定了只能是静态绑定的。(不是我胡诌,还是大师说的)

原因说了,该记解决方式了:
结合35课上学到的知识,我们可以用非虚函数接口(NVI)来解决这个问题,看代码

class  AClass
{
   
public:
      
void func(int param = 123)
      
{
         funcImpl(param);
      }

   
private:
      
virtual void funcImpl( int real_param ) = 0;
   
//..
}
;

class  AClassDerived :  public  AClass
{
   
private:
      
virtual void funcImpl( int real_param )
      
{
         
//do whatever you feel like to do here..
      }

   
//..
}
;
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值