• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

十个例子让你完全搞懂C++的虚函数(不懂来找我)

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

 


我的公众号 「Linux云计算网络」(id: cloud_dev),号内有 10T 书籍和视频资源,后台回复 「1024」 即可领取,分享的内容包括但不限于 Linux、网络、云计算虚拟化、容器Docker、OpenStack、Kubernetes、工具、SDN、OVS、DPDK、Go、Python、C/C++编程技术等内容,欢迎大家关注。


Author: bakari  Date: 2012.4.8

装载引用请注明出处:http://www.cnblogs.com/bakari/archive/2012/08/12/2635369.html   谢谢!

虚函数是C++中非常重要的一个概念,它最大的好处是能够触发动态绑定。C++中的函数默认不使用动态绑定,要触发动态绑定,必须满足 两个条件:

第一,只有指定为虚函数的成员函数才能进行动态绑定,成员函数默认为非虚函数,非虚函数不进行动态绑定;

第二,必须通过基类类型的指针或引用进行函数的调用。具体理解指针或引用在使用继承层次中某一类型的对象时会发生什么,本文不展开讨论,

这两天主要研习了虚函数的具体应用这一块,而它的应用又非常广泛,学MFC的应该能够感受到它的强大,要说是总结也不一定能够总结全,本人目前也处在studying中,所以用10个具体的例子来说明。例子是从难 到易,看到的朋友如果懂前面的可以不用看后面的。每一个例子就是一个类,通过类在内存中的布局来形象地分析虚函数究竟是如何运作的。图表示可能抽象一点,一般带有V开头的表示一个虚函数表,如果是学过编译原理这门课就很容易看懂,没学过的只要懂虚函数的一些机制,耐着性子也是没问题的。每个图示都配有相应的代码。可以对照着代码来看。

1、  虚函数继承的复杂例子

2、  菱形继承无虚拟继承的情况

3、  虚拟继承的简单情况

4、  单一普通继承(无虚函数)

5、  单一继承(含虚函数)(虚函数表只有一个)

6、  多重继承(不含虚函数)

7、  多重继承(一个含虚函数,一个不含虚函数)

8、  多重继承(两个都含有虚函数)

9、  纯虚汗继承

10、 private 的虚函数

 

1、虚函数继承的复杂例子,见下图:

见图:左边是这个类的内存布局,右边是继承图示。 farther类和Uncle类都是虚拟继承,其内部也都有偏移表,但我觉得这两个表只是内部隐藏的,不在Son的内存布局中表示出来,本题Son的内存只有32个字节,如果表示出来就不止32个了,但是下面这个地方在内存中显示是00 00 00 00,我猜想是不是GrandFather的偏移地址。

VbtSon(Father)

Farther~Num

VbtSon(Uncle)

Uncle~Num

Son~Num

Offset(这个地方??)

Vftable(GrandFather)

GrandFather~Num

                                        

 

 例子代码:

 1 class GrandFather
 2 {
 3 public:
 4     GrandFather():i_G(5){cout<<"GrandFather() is called!"<<endl;}
 5     virtual ~GrandFather(){cout<<"~GrandFather() is called!"<<endl;}
 6 public:
 7     virtual void Test(){cout<<"GrandFather::Test() is called!"<<endl;}
 8 private:
 9     int i_G;
10 };
11 
12 class Father: virtual public GrandFather             //虚拟继承
13 {
14 public:
15     Father():i_F(7){cout<<"Father() is called!"<<endl;};
16     virtual ~Father(){cout<<"~Father() is called!"<<endl;}
17 public:
18     virtual void Test(){cout<<"Father::Test() is called!"<<endl;}
19 private:
20     int i_F;
21 };
22 
23 class Uncle: virtual public GrandFather                          //虚拟继承
24 {
25 public:
26     Uncle():i_U(3){cout<<"Uncle is called!"<<endl;}
27     virtual ~Uncle(){cout<<"~Uncle  is called!"<<endl;}
28 public:
29     virtual void Test(){cout<<"Uncle ::Test() is called!"<<endl;}
30 private:
31     int i_U;
32 };
33 
34 class Son:public Father,public Uncle                    
35 {
36 public:
37     Son():i_S(9){cout<<"Son is called!"<<endl;};
38     virtual ~Son(){cout<<"~Son  is called!"<<endl;}
39 public:
40     virtual void Test(){cout<<"Son ::Test() is called!"<<endl;}
41 private:
42     int i_S;
43 };
44 
45 int main(void)
46 {
47     Son p;
48     p.Test();
49     cout<<sizeof(Son)<<endl;
50     cout<<sizeof(Father)<<endl;
51     cout<<sizeof(GrandFather)<<endl;
52     return 0;
53 }

运行情况:

 

2、  菱形继承无虚拟继承的情况

VPTr1(Father)

GrandFarther~Num

Father~Num

VPtr(Uncle)

GrandFarther~Num

Uncle~Num

Son~Num

                         

 1 #include<iostream>
 2 using namespace std;
 3 class GrandFather
 4 {
 5 public:
 6     GrandFather():i_G(5){cout<<"GrandFather() is called!"<<endl;}
 7     virtual ~GrandFather(){cout<<"~GrandFather() is called!"<<endl;}
 8 public:
 9     virtual void Test(){cout<<"GrandFather::Test() is called!"<<endl;}
10 private:
11     int i_G;
12 };
13 class Father:   public GrandFather          //无虚拟继承
14 {
15 public:
16     Father():i_F(7){cout<<"Father() is called!"<<endl;};
17     virtual ~Father(){cout<<"~Father() is called!"<<endl;}
18 public:
19     virtual void Test(){cout<<"Father::Test() is called!"<<endl;}
20 private:
21     int i_F;
22 };
23 
24 class Uncle:   public GrandFather             //无虚拟继承
25 {
26 public:
27     Uncle():i_U(3){cout<<"Uncle is called!"<<endl;}
28     virtual ~Uncle(){cout<<"~Uncle  is called!"<<endl;}
29 public:
30     virtual void Test(){cout<<"Uncle ::Test() is called!"<<endl;}
31 private:
32     int i_U;
33 };
34 
35 class Son:public Father,public Uncle
36 {
37 public:
38     Son():i_S(9){cout<<"Son is called!"<<endl;};
39     virtual ~Son(){cout<<"~Son  is called!"<<endl;}
40 public:
41     virtual void Test(){cout<<"Son ::Test() is called!"<<endl;}
42 private:
43     int i_S;
44 };
45 
46 int main(void)
47 {
48     Son p;
49     p.Test();
50     cout<<sizeof(Son)<<endl;
51     cout<<sizeof(Father)<<endl;
52     cout<<sizeof(GrandFather)<<endl;
53     
54     return 0;
55 }

运行情况:

            

3、  虚拟继承的简单情况 见下图:

VPTrD(A)              4      

Offset(A)              4

A~number             4

D~number             4

VPtr(Base)            4

Base~Number  

 

12 + 3cc + 4 = 40

                                

 1 class Base
 2 {
 3 public:
 4     Base(){strcpy_s(ch_rc,"abcdefg");}                  //初始化Base()::im
 5 public:
 6    virtual void Read(){cout<<"Base::Read()is called!"<<endl;}
 7 private:
 8     char ch_rc[12];
 9     bool ir;
10     int  im;                   
11 };
12 class A: virtual public Base     //虚拟继承
13 {
14 public:
15     A():im_A(5){}                        //初始化A()::im_A
16 public:
17     virtual void Read(){cout<<"A::Read()is called!"<<endl;}
18 private:
19     int im_A;
20 };
21 class D:public A
22 {
23 public:
24     D():im_D(3){}          
25 public:
26     virtual void Read(){cout<<"D::Read()is called!"<<endl;}
27 private:
28     int im_D;
29 };
30 int _tmain(int argc, _TCHAR* argv[])
31 {
32     D obj;
33     cout<<sizeof(D)<<endl;
34     return 0;
35 }

运行情况:

 

4、单一普通继承(无虚函数)(这个没什么好说的)

                                                                                                      内存布局

Father~Number

Son~Number

 1 class Father
 2 {
 3 public:
 4     Father(){cout<<"Father() is called!"<<endl;}
 5     void TestF(const int &m){
 6         i_B=m;
 7         cout<<"Father::TestF() is called!"<<endl;
 8     }
 9     void Test(){cout<<"Base::Test() is called!"<<endl;}
10     ~Father(){cout<<"~Father() is called!"<<endl;}
11 private:
12     int i_B;
13 };
14  
15 class Son:public Father
16 {
17 public:
18     Son():i_A(5){cout<<"Son() is called!"<<endl;}
19      void Test(){cout<<"Son::Test() is called!"<<endl;}
20      ~Son(){cout<<"~Son() is called!"<<endl;}
21 private:
22     int i_A;
23 };
24 int main(int argc,char *argv[])
25 {
26     Father *p=new Son;
27     //Father *p=NULL;
28     p->Test();
29     delete p;
30     p=NULL;
31     cout<<sizeof(Son)<<endl;
32     return 0;
33 }

 

5、单一继承(含虚函数)(虚函数表只有一个)见图:

VPTr(father)

Father~number

Son~number

Child~number

                        

 1 #include<iostream>
 2 using namespace std;
 3 class Father
 4 {
 5 public:
 6     Father(){cout<<"Father() is called!"<<endl;}
 7     virtual  void Test(){cout<<"Base::Test() is called!"<<endl;}
 8     virtual ~Father(){cout<<"~Father() is called!"<<endl;}
 9 private:
10     int i_B;
11 };
12  
13 class Son:public Father
14 {
15 public:
16     Son():i_A(5){cout<<"Son() is called!"<<endl;}
17      void Test(){cout<<"Son::Test() is called!"<<endl;}
18      ~Son(){cout<<"~Son() is called!"<<endl;}
19 private:
20     int i_A;
21 };
22 int main(int argc,char *argv[])
23 {
24     Father *p=new Son;
25     //Father *p=NULL;
26     p->Test();
27     delete p;
28     p=NULL;
29     cout<<sizeof(Son)<<endl;
30     return 0;
31 }

运行情况:

 

6、多重继承(不含虚函数)(这个也没什么好说的)

直接看代码:

 1 #include<iostream>
 2 using namespace std;
 3 class Father
 4 {
 5 public:
 6     Father():i_B(6){cout<<"Father() is called!"<<endl;}
 7      void TestF(const int &m){
 8         i_B=m;
 9         cout<<"Father::TestF() is called!"<<endl;
10     }
11       void Test(){cout<<"Father::Test() is called!"<<endl;}
12      ~Father(){cout<<"~Father() is called!"<<endl;}
13 private:
14     int i_B;
15 };
16 class Son
17 {
18 public:
19     Son():i_A(5){cout<<"Son() is called!"<<endl;}
20       void Test(){cout<<"Son::Test() is called!"<<endl;}
21       ~Son(){cout<<"~Son() is called!"<<endl;}
22 private:
23     int i_A;
24 };
25 
26 class Child:public  Father,public Son      //多重继承
27 {
28 public:
29     Child():i_C(5){cout<<"Child() is called!"<<endl;}
30      void Test(){cout<<"Child::Test() is called!"<<endl;}
31      ~Child(){cout<<"~Child() is called!"<<endl;}
32 private:
33     int i_C;
34 };
35 int main(int argc,char *argv[])
36 {
37     Father *p=new Child;
38     //Father *p=NULL;
39     p->Test();
40     cout<<sizeof(Son)<<endl;
41     cout<<sizeof(Child)<<endl;
42     return 0;
43 }

 

7、多重继承(一个含虚函数,一个不含虚函数)(类似单一继承)

VPTr(father)

Father~number

Son~number

Child~number

                         

 1 #include<iostream>
 2 using namespace std;
 3 
 4 class Father
 5 {
 6 public:
 7     Father():i_B(6){cout<<"Father() is called!"<<endl;}
 8     virtual  void TestF(const int &m){
 9         i_B=m;
10         cout<<"Father::TestF() is called!"<<endl;
11     }
12       virtual void Test(){cout<<"Father::Test() is called!"<<endl;}
13      virtual  ~Father(){cout<<"~Father() is called!"<<endl;}
14 private:
15     int i_B;
16 };
17  
18 class Son
19 {
20 public:
21     Son():i_A(5){cout<<"Son() is called!"<<endl;}
22       void Test(){cout<<"Son::Test() is called!"<<endl;}
23       ~Son(){cout<<"~Son() is called!"<<endl;}
24 private:
25     int i_A;
26 };
27 
28 class Child:public  Father,public Son
29 {
30 public:
31     Child():i_C(5){cout<<"Child() is called!"<<endl;}
32      void Test(){cout<<"Child::Test() is called!"<<endl;}
33      ~Child(){cout<<"~Child() is called!"<<endl;}
34 private:
35     int i_C;
36 };
37 int main(int argc,char *argv[])
38 {
39     Father *p=new Child;
40     //Father *p=NULL;
41     p->Test();
42     cout 

鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
mysqlconnectorc++插入数据发布时间:2022-07-13
下一篇:
c# 多线程 创建对象实例发布时间:2022-07-13
热门推荐
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap