是否只有通过基类指针或引用间接指向派生类子类型时,多态性才会起作用?

来自:http://www.ithao123.cn/content-971985.html


问题2:是否只有通过基类指针或引用间接指向派生类子类型时,多态性才会起作用?

等级:初级

 

只有通过基类指针或引用间接指向派生类子类型时,多态性才会起作用。使用基类对象并不会保留派生类的类型身份,不再具备多态性。

 

深入讨论:

这个问题和答案有一点模糊,让我们通过一个示例来明确这个问题。

#include <iostream>

class Base {

public:

         virtual void f() {

                   std::cout<< “Calling Base::f()…/n”;

         };

};

 

class Derived: public Base {

public:

         virtual void f() {

                   std::cout<< “Calling Derived::f()…/n”;

         };

};

类Base和Derived,Derived从Base继承而来,子类Derived覆盖(Override)了基类Base中定义的虚函数f()。如果通过基类对象指针或引用来调用虚函数f(),那么会调用类对象的动态类型中所定义的函数,多态性发挥了作用。所以,如果执行如下代码:

Base* pb = new Base();

Base* pd = new Derived();

 

pb->f();

pd->f();

 

Base& rb = *pb;

Base& rd = *pd;

 

rb.f();

rd.f();

会得到如下结果。

Calling Base::f()...

Calling Derived::f()...

Calling Base::f()...

Calling Derived::f()...

如果通过基类对象来调用虚函数f(),基类对象并不会保留派生类的类型身份,不再具备多态性。所以,如果执行如下代码:

Derived d;

Base b = d; // d被“切割”成一个Base对象

d.f();

会得到如下结果。

Calling Base::f()...

尽管用d初始化b是合法的,但是b不再是一个Derived对象。在初始化b之前,d的Derived部分被切除,成为了一个Base对象。所以,最后调用了方法Base::f()。

这也是C++被人广为诟病的特性之一,作为一种面向对象编程语言,我们必须使用指针以引用而不是对象来支持面向对象程序设计

可能有一些善于思考的读者会想到一种情况:如果基类对象通过解引用操作符*获得,调用虚函数是否具备多态性?例如,执行如下代码会得到什么结果:

Base* pb = new Base();

Base* pd = new Derived();

Base b = *pd;

b.f();

(*pd).f();

执行结果如下:

Calling Base::f()...

Calling Derived::f()...

为什么(*pd).f()会调用Derived::f()?因为通过解引用操作符*获得不是一个基类Base对象,而是子类Derived对象。

 

参考资料:

《C++ Primer》第四版章节17.5导言部分。

《Inside C++ Object Model》章节1.3。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值