Note of Justin

关于工作和读书的笔记

  C++博客 :: 首页 :: 联系 :: 聚合  :: 管理
  47 Posts :: 0 Stories :: 45 Comments :: 0 Trackbacks

留言簿(14)

搜索

  •  

积分与排名

  • 积分 - 51720
  • 排名 - 433

最新评论

阅读排行榜

评论排行榜

[原创文章欢迎转载,但请保留作者信息]
Justin 于 2010-01-26

条例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..
      }

   
//..
}
;
对默认参数的设定放在了一个非虚函数中,这样一来,就不会有以上说的顾虑了。
posted on 2010-03-04 16:47 Justin.H 阅读(387) 评论(0)  编辑 收藏 引用 所属分类: Effective C++ 炒冷饭

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理