分享

02选择题: 多态

 雪柳花明 2017-03-05
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
    #include "stdio.h"
 
class A
{
public:
    virtual void Test()
    {
        printf("A test\n");
    }
};
class B: public A
{
public:
    void func()
    {
        Test();
    }
    virtual void Test()
    {
        printf("B test\n");
    }
};
class C: public B
{
public:
    virtual void Test()
    {
        printf("C test\n");
    }
};
void main()
{
    C c;
    ((B *)(&c))->func();
    ((B)c).func();
}

该程序的执行结果

C test				
B test

解释一:
((  *)(& c ))-> func (); 是多态行为 
(( B ) c ). func (); 不是多态行为。 

参见 effective c++ P170 “令客户通过public non-virtual成员函数间接调用private virtual函数,称之为non-virtual interface(NVI)手法。”


解释二:
相信:((B)c).func();这句大家都懂,无非就是静态调用嘛(要启用动态调用需要由基类的指针或引用来发起,而且调用的函数得是虚函数); 既然调用前c对象被强制转换为B类型,那么调用的自然是B类中的对应函数了。
对于:((B*)(&c))->func(); 首先,func函数在类B中并不是虚函数,所以语句中调用的func是B类中的函数;其次,在func中调用了虚函数,也就是此时发生了动态调用(调用func是是静态的),相当于在B类的func中发生了如下调用:((B *)(&c))->Test();满足动态调用的要求,调用的是C类的test函数。

解释三:
这是  向上造型  的两类,第一类是指针和引用,不产生切割,如本题的 ((B *)(&c))->func();;第二类是直接转换对象类型,会产生切割,如本题的((B)c).func();
产生切割时,把子类多余的不部分去除了,并把虚表指针vptr重新指向父类的虚函数表。因为vptr变了,所以输出B test

解释四:
C c;声明了一个C类的对象c。
((B *)(&c))->func(); 用B类的指针指向C类对象,此时func()是B类中的,由于Test()声明为虚函数,所以根据实际对象找到虚函数表,得到C中的虚函数输出"Ctest".
((B)c).func();
将c转化为B 类,(相当于把一个范围大的强制转化为范围小的如double 类型转化为int ),此时c不再是C类,而就是一个B 类的对象。




    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多