曲径通幽论坛

 找回密码
 立即注册
搜索
查看: 2489|回复: 0
打印 上一主题 下一主题

虚函数的几点总结

[复制链接]

4917

主题

5879

帖子

3万

积分

GROAD

曲径通幽,安觅芳踪。

Rank: 6Rank: 6

积分
34382
跳转到指定楼层
楼主
发表于 2013-10-17 13:17:20 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
虚函数(虚方法)是为了满足“多态”而提出的。多态,即具有多种形态,是一种接口多种方法的体现。比如说,手机都要具备音量调节这种接口,但是不同的手机对该接口的内部实现(方法)不同,如一般的手机(基类)要求具备物理上下键的调节,而现代智能手机(派生类)还需要具备通过点击触摸屏来调节。

声明虚方法需要在方法前面使用 virtual 关键字来声明。

对于通过引用或指针来使用方法,有两种情况:

如果没有使用关键字 virtual 来声明,那么就是一般的方法,程序将根据引用类型或指针类型来选择方法。比较下面代码:
  1. BaseClass ordinary("Window", 1000, 2000);
  2. DerivedClass VIP("VIP Window", 3000, 5000);

  3. BaseClass &b1_ref = Ordinary;
  4. BaseClass &b2_ref = VIP;

  5. b1_ref.View_Account();
  6. b2_ref.View_Account();
复制代码
其中,BaseClass 是基类;DerivedClass 是 BaseClass 的派生类;View_Account() 是方法。
上面,View_Account() 这个方法在基类和派生类中都有。b1_ref 和 b2_ref 都是基类的引用,虽然派生类的对象 VIP 赋给了 b2_ref ,但当 b2_ref 调用 View_Account() 这个方法时,仍然调用的是基类中的方法,而非派生类中的方法。至于为什么,可参考《派生类与基类之间的几个特殊关系》。上面代码中使用的是引用,如果换做指针,行为也类似。


如果上面代码中的 View_Account() 是虚的,那么行为将不同,那么 b2_ref.View_Account(); 这条语句使用的是 DerivedClass 中的方法,而不是 BaseClass 中的方法。同样,将引用换做指针,那么行为与之类似。


注意,如果要在派生类中重新定义基类的方法,通常应该将基类方法声明为虚的。这样,正如上所示,程序将根据对象类型而不是引用或指针的类型来选择方法的版本。另外,为基类声明一个虚析构函数也是一种惯例。

除非类不用做基类,否则的话就应当将析构函数声明为虚函数。比如,雇员 Employee 是基类,歌手 Singer 是派生类,并添加一个 char * 成员,该成员指向由 new 分配的内存。那么当 Singer 对象过期时,应当调用 ~Singer() 析构函数来释放内存。


现在看下面的代码:
  1. Employee *pe = new Singer;   // 合法,基类指针可以指向派生类对象
  2. ... ...
  3. delete pe;       // 调用 ~Employee() 还是 ~Singer() ?
复制代码
如果不使用 virtual 将析构函数声明为虚析构函数的话,那么 delete 语句将调用的是 ~Employee() 析构函数。这可以释放由 Singer 对象中的 Employyee 部分指向的内存,但不会释放新的类成员指向的内存(如上的 char *)。但是,如果析构函数是虚的,那么上述代码将线调用 ~Singer 析构函数,释放由 Singer() 组件指向的内存;然后在调用 ~Employee() 析构函数来释放由 Employee 组件指向的内存。这样一来,问题就没有了。

事实上,即使不是基类,你将析构函数定义为虚的,也不会有错,但会影响效率。通常,应该给基类提供一个虚析构函数,即使它并不需要。

另外,构造函数不能是虚函数。在创建派生类对象时,将调用派生类的构造函数,而不是基类的构造函数,然后派生类的构造函数将使用基类的一个构造函数,但这种调用顺序并不是继承机制。因此,派生类不继承基类的构造函数,所以将类构造函数声明为虚的没什么意义。


您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|曲径通幽 ( 琼ICP备11001422号-1|公安备案:46900502000207 )

GMT+8, 2024-5-14 12:41 , Processed in 0.065963 second(s), 26 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表