如何确定C++继承层次中的函数调用

  1 ```cpp
  2 
  3 
  4 //============================================================================
  5 // Name        : TS.cpp
  6 // Author      : jiudianren
  7 // Version     :
  8 // Copyright   : Your copyright notice
  9 // Description : Hello World in C++, Ansi-style
 10 //============================================================================
 11 
 12 #include <iostream>
 13 #include <functional>
 14 
 15 using namespace std;
 16 
 17 
 18 class A
 19 {
 20 protected:
 21     int m_data;
 22 public:
 23     A(int data = 0)
 24     {
 25         m_data = data;
 26     }
 27     int GetData()
 28     {
 29         return doGetData();
 30     }
 31     virtual int doGetData()
 32     {
 33         return m_data;
 34     }
 35 };
 36 
 37 
 38 
 39 class B: public A
 40 {
 41 protected:
 42     int m_data;
 43 public:
 44     B(int data = 1)
 45     {
 46         m_data = data;
 47     }
 48     int doGetData()
 49     {
 50         return m_data;
 51     }
 52 };
 53 
 54 
 55 class C: public B
 56 {
 57 protected:
 58     int m_data;
 59 public:
 60     C(int data = 2)
 61     {
 62         m_data = data;
 63     }
 64 
 65     int doGetData()
 66     {
 67         return m_data;
 68     }
 69 };
 70 
 71 void ref(C* & d)
 72 {
 73     cout<<d->GetData()<<endl;            //题1
 74     cout<<d->A::GetData()<<endl;         //题2
 75     cout<<d->B::GetData()<<endl;         //题3
 76     cout<<d->C::GetData()<<endl;         //题4
 77 
 78     cout<<d->doGetData()<<endl;          //题5
 79     cout<<d->A::doGetData()<<endl;       //题6
 80     cout<<d->B::doGetData()<<endl;       //题7
 81     cout<<d->C::doGetData()<<endl;       //题8
 82 }
 83 int main()
 84 {
 85     C c(10);
 86     cout<<c.GetData()<<endl;            //题1
 87     cout<<c.A::GetData()<<endl;         //题2
 88     cout<<c.B::GetData()<<endl;         //题3
 89     cout<<c.C::GetData()<<endl;         //题4
 90 
 91     cout<<c.doGetData()<<endl;          //题5
 92     cout<<c.A::doGetData()<<endl;       //题6
 93     cout<<c.B::doGetData()<<endl;       //题7
 94     cout<<c.C::doGetData()<<endl;       //题8
 95 
 96     cout<<"sssssssssss"<<endl;       //题8
 97     C *f=new C(11);
 98     C *d=f;
 99     cout<<d->GetData()<<endl;            //题1
100     cout<<d->A::GetData()<<endl;         //题2
101     cout<<d->B::GetData()<<endl;         //题3
102     cout<<d->C::GetData()<<endl;         //题4
103 
104     cout<<d->doGetData()<<endl;          //题5
105     cout<<d->A::doGetData()<<endl;       //题6
106     cout<<d->B::doGetData()<<endl;       //题7
107     cout<<d->C::doGetData()<<endl;       //题8
108 
109     cout<<"sssssssssss"<<endl;       //题8
110     ref(f);
111     return 0;
112 }
113 
114 
115 ```

理解C++中继承层次的关键在于理解如何确定函数调用。确定函数调用遵循以下四个步骤:

1)   首先确定进行函数调用的对象、引用或指针的静态类型。

2)   在该类中查找函数,如果找不到,就在直接基类中查找,如此循着类的继承链往上找,直到找到该函数或者查找完最后一个类。如果不能在类或其相关类中找到该名字,则调用是错误的。

3)   一旦找到了该名字,就进行常规类型检查,查看该函数调用是否合法。

4)   <i>若函数调用合法,编译器就生成代码。如果函数是虚函数且通过引用或指针调用,则编译器生成代码以确定根据对象的动态类型运行哪个函数版本,否则,编译器生成代码直接调用函数。

<ii>若函数调用不合法,则调用是错误的,且不再像(2)一样循着继承链往上找。

 

 

 

 

 

 

 

 

题1----题8

构造函数从最上层的基类开始构造,各个类的同名变量没有形成覆盖,都是单独的变量。
1:
静态类型为C类,故在C类中找GetData()函数,C类中没有GetData()函数,由步骤(2),在其直接基类B类中查找,B类中也没有,再在A类中找,在A类中找到,且常规类型检查无误,调用合法,运行之。在其函数体类调用的doGetData()是虚函数,但不是通过引用或指针调用,故没有动态绑定,则由静态类型决定调用哪一个版本的doGetData(),静态类型为C类,C类中没有doGetData(),在其基类B类中找,找到,运行之,返回的是B::m_data,其值为默认实参值1。故本行输出1。
其他题类似,答案为1,1,1,1,1,0,1,1。

 

posted @ 2016-07-10 09:00  九点人  阅读(1333)  评论(0编辑  收藏  举报