在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
装载引用请注明出处: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的偏移地址。
例子代码: 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、 菱形继承无虚拟继承的情况
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、 虚拟继承的简单情况 见下图:
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、单一普通继承(无虚函数)(这个没什么好说的) 内存布局
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、单一继承(含虚函数)(虚函数表只有一个)见图:
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、多重继承(一个含虚函数,一个不含虚函数)(类似单一继承)
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 |
2023-10-27
2022-08-15
2022-08-17
2022-09-23
2022-08-13
请发表评论