继承,菱形继承,多态,虚拟继承,多虚拟继承,菱形虚拟继承

来源:互联网 发布:mongodb 连接数据库 编辑:程序博客网 时间:2024/05/19 13:44

下面的代码主要写了关于:

(1).继承和派生的关系

(2).6个默认函数的继承(拷贝,拷贝构造,赋值,析构,...)

(3).普通菱形继承

(4).多重虚继承

(5).多态

(6).虚表

(7).虚菱形继承

     其中涉及到了很多C++中的内容,如<重载,隐藏,覆盖>,<虚基类,虚函数>,<单继承,多继承(菱形继承)> 等等

<span style="font-family:Microsoft YaHei;font-size:14px;">#ifndef INHERIT_H_#define INHERIT_H_#include <iostream>#include <string>using namespace std;//继承和派生//继承与派生类的关系namespace Relation{class Person  { //基类public:void fun(){}void show(){cout << _name << endl;}~Person(){cout << "~Person" << endl;}public:string _name;};class Student :protected Person{ // 派生类public:void show(){cout << _name << " " << _id << endl;}~Student(){cout << "~Student" << endl;//~Person(); //不能手动调用Person::~Person(); //这样才可以调用}public:/* 将数据成员设置成public确实不符合封装的理念,但是我们是在找规律,所以这样做可以在类外改变数据成员,易于观察变化*/int _id; };void test(){Person p;Student s;Person* p1 = &p;//Person* p2 = &s; //共有继承时可以,保护和私有继承时却不可以//s->fun(); //保护或者私有继承的时候,s不能访问的东西,p2是可以访问的,不合逻辑//p2->fun(); //effective c++ 中讲到的has_a关系Person& p3 = p;//Person& p4 = s; //共有继承时可以,保护和私有继承时却不可以Student* s1 = (Student*)&p;//s1->_id = 0; //该段不属于s1,不能访问(写),相当于是借来的Student* s2 = &s;Student& s3 = (Student&)p;//s3._id = 0; //该段不属于s3,不能访问(写),相当于是借来的Student& s4 = s;}}//6个默认函数的继承namespace FUNC{class Person{public:Person(const char* str = ""):_name(str){//构造函数cout << "Person(const char* str = "")" << endl;}Person(const Person& p):_name(p._name){//拷贝构造函数cout << "Person(const Person& p)" << endl;}Person& operator=(const Person& p){//赋值语句if (this != &p){_name = p._name;cout << "Person& operator=(const Person& p)" << endl;}return *this;}~Person(){//析构函数cout << "~Person" << endl;}public:string _name;};class Student :public Person{public:Student(const char* s = "", int id = 0):Person(s), _id(id){cout << "Student(const char* s ,int id) " << endl;}Student(const Student& s):Person(s) //发生切片{_id = s._id;cout << "Student(const Student& s)" << endl;}Student& operator=(const Student& s){if (this != &s){Person::operator=(s); //也会发生切片_id = s._id;cout << "Student& operator=(const Student& s)" << endl;}return *this;}~Student(){cout << "~Student" << endl;//~Person(); //不能手动调用//Person::~Person(); //这样才可以调用}public:void show(){cout << _name << " " << _id << endl;}int _id;};void test(){Person p("hello");Student s1("hello world", 2);Student s2(s1);Student s3;s3 = s2;}}//多继承(菱形继承)namespace MULTIPLE_INHERITANCE{class A{public:void func_a(){cout << "A-func" << endl;}int a;};class B : virtual public A //继承A{public:void func_b(){cout << "B-func" << endl;}int b;};class C :virtual public A //继承A{public:void func_c(){cout << "C-func" << endl;}int c;};class D :public B, public C //继承B,C{public:void func_d(){cout << "D-func" << endl;}int d;};void test(){A a;B b;C c;D d;/***************************************************************************************************///通过内存变化可分析,虚继承与普通继承的区别//非虚基类/*d.B::a = 1;d.b = 2;d.C::a = 3;d.c = 4;d.d = 5;cout << sizeof(a) << endl; //4cout << sizeof(b) << endl; //8cout << sizeof(c) << endl; //8cout << sizeof(d) << endl; //20 可以看出a被继承了两次*///虚基类d.B::a = 1;d.b = 2;d.C::a = 3;d.c = 4;d.d = 5;cout << sizeof(a) << endl; //4cout << sizeof(b) << endl; //12 a,b,加上一个指向虚基类的指针(严格来说不是指针,只是偏移量)cout << sizeof(c) << endl; //12 a,c,加上一个指向虚基类的指针(严格来说不是指针,只是偏移量)cout << sizeof(d) << endl; //24 a b c d/***************************************************************************************************/}}//多重虚继承namespace MULTIPLE_MANY{class A{public:virtual void funA(){cout << "A-fun" << endl;}virtual void fun_A(){cout << "A-fun_A" << endl;}int a;};class B{public:virtual void funB(){cout << "B-fun" << endl;}virtual void fun_B(){cout << "B-fun_B" << endl;}int b;};class C{public:virtual void funC(){cout << "C-fun" << endl;}virtual void fun_C(){cout << "C-fun_C" << endl;}int c;};class D :public A, public B, public C{public:virtual void funA(){cout << "D-funA" << endl;}virtual void funB(){cout << "D-funB" << endl;}virtual void funC(){cout << "D-funC" << endl;}virtual void funD(){cout << "fun-D" << endl;}int d;};typedef void(*Fun)();void PrintVtable(int* PTable){printf("虚表地址:%p\n", PTable);for (int i = 0; PTable[i] != 0; ++i){printf("第%d个虚函数:%p ", i, PTable[i]);Fun p = (Fun)PTable[i];p();}printf("\n");}void test(){D d;d.a = 1;d.b = 2;d.c = 3;d.d = 4;//虚表Aint* Vtable1 = (int*)*(int*)(&d); //根据在内存中分布位置来转化PrintVtable(Vtable1);//虚表Bint* Vtable2 = (int*)*((int*)(&d) + sizeof(A) / 4); //根据在内存中分布位置来转化PrintVtable(Vtable2);//虚表Cint* Vtable3 = (int*)*((int*)(&d) + (sizeof(A)+sizeof(B)) / 4); //根据在内存中分布位置来转化PrintVtable(Vtable3);}}//多态namespace POLYMORPHISM{class A{public:void fun1() //隐藏{cout << "A-func-1" << endl;}virtual void fun2() //覆盖的条件需要注意{cout << "A-func-2" << endl;}virtual A* fun3(){cout << "A-func-3(协变)" << endl;return this;}//*重载的条件:作用域必须相同*//下面两个函数才构成重载void fun4(){cout << "void fun4()" << endl;}void fun4(int a){cout << "void fun4(int)重载" << endl;}private:int a;};class B : public A //继承A{public:int fun1(){cout << "B-func-1隐藏" << endl;return 0;}virtual void fun2() //覆盖的条件需要注意{cout << "B-func-2覆盖" << endl;}virtual B* fun3(){cout << "B-func-3覆盖(协变)" << endl;return this;}private:int b;};void test(){A a;B b;A* p1;p1 = &a;cout << "隐藏" << endl;a.fun1();b.fun1();cout << "重载" << endl;p1->fun4();p1->fun4(0);cout << "隐藏和覆盖" << endl;p1->fun1();p1->fun2();p1->fun3();p1 = &b;p1->fun1();p1->fun2();p1->fun3();}}//虚表namespace VIRTUAL_FUNC{class Base1 {public:virtual void f() { cout << "Base1::f" << endl; }virtual void g() { cout << "Base1::g" << endl; }virtual void h() { cout << "Base1::h" << endl; }};class Base2 {public:virtual void f() { cout << "Base2::f" << endl; }virtual void g() { cout << "Base2::g" << endl; }virtual void h() { cout << "Base2::h" << endl; }};class Base3 {public:virtual void f() { cout << "Base3::f" << endl; }virtual void g() { cout << "Base3::g" << endl; }virtual void h() { cout << "Base3::h" << endl; }};class Derive : public Base1, public Base2, public Base3 {public:virtual void f() { cout << "Derive::f" << endl; }virtual void g1() { cout << "Derive::g1" << endl; }};typedef void(*Fun)(void);void test(){Fun pFun = NULL;Derive d;int** pVtab = (int**)&d;//Base1's vtable//pFun = (Fun)*((int*)*(int*)((int*)&d+0)+0);pFun = (Fun)pVtab[0][0];pFun();//pFun = (Fun)*((int*)*(int*)((int*)&d+0)+1);pFun = (Fun)pVtab[0][1];pFun();//pFun = (Fun)*((int*)*(int*)((int*)&d+0)+2);pFun = (Fun)pVtab[0][2];pFun();//Derive's vtable//pFun = (Fun)*((int*)*(int*)((int*)&d+0)+3);pFun = (Fun)pVtab[0][3];pFun();//The tail of the vtablepFun = (Fun)pVtab[0][4];cout << pFun << endl;//Base2's vtable//pFun = (Fun)*((int*)*(int*)((int*)&d+1)+0);pFun = (Fun)pVtab[1][0];pFun();//pFun = (Fun)*((int*)*(int*)((int*)&d+1)+1);pFun = (Fun)pVtab[1][1];pFun();pFun = (Fun)pVtab[1][2];pFun();//The tail of the vtablepFun = (Fun)pVtab[1][3];cout << pFun << endl;//Base3's vtable//pFun = (Fun)*((int*)*(int*)((int*)&d+1)+0);pFun = (Fun)pVtab[2][0];pFun();//pFun = (Fun)*((int*)*(int*)((int*)&d+1)+1);pFun = (Fun)pVtab[2][1];pFun();pFun = (Fun)pVtab[2][2];pFun();//The tail of the vtablepFun = (Fun)pVtab[2][3];cout << pFun << endl;}}//虚钻石继承namespace VIRTUAL_RING{typedef void(*Func)();  //函数指针void PrintVTable(int *VTable){cout << "虚表地址:" << VTable << endl;for (int i = 0; VTable[i] != 0; i++){printf("第VTable[%d]是:OX%p->", i, VTable[i]);Func p = (Func)VTable[i];p();}cout << endl;}class A{public:virtual void fun1(){cout << "A-func1" << endl;}virtual void fun2(){cout << "A-func2" << endl;}int a;};class B : virtual public A //继承A{public:virtual void fun1(){cout << "B-func1" << endl;}virtual void fun3(){cout << "B-func3" << endl;}int b;};class C :virtual public A //继承A{public:virtual void fun1(){cout << "C-func1" << endl;}virtual void fun4(){cout << "C-func4" << endl;}int c;};class D :public B, public C //继承B,C{public:virtual void fun1(){cout << "D-func1" << endl;}virtual void fun5(){cout << "D-func5" << endl;}int d;};void test(){cout << "虚表A:" << endl;A a;int *fa1 = (int *)(*(int *)&a);PrintVTable(fa1);cout << "虚表B:" << endl;B b;int* fa2 = (int *)(*(int *)&b);PrintVTable(fa2);fa2 = (int *)*(int *)((char *)&b + sizeof(B)-sizeof(A));PrintVTable(fa2);cout << "虚表C:" << endl;C c;int* fa3 = (int *)(*(int *)&c);PrintVTable(fa3);fa3 = (int *)*(int *)((char *)&c + sizeof(C)-sizeof(A));PrintVTable(fa3);cout << "虚表D" << endl;D d;d.a = 1;d.b = 2;d.c = 3;d.d = 4;    //记得打开调试找到&d,然后好好看看地址分配,便于下面的操作//虚表1int* fa4 = (int *)(*(int *)&d);PrintVTable(fa4);//虚表2fa4 = (int*)*((int*)&d + sizeof(B) / 4 - 2); //根据在内存中的分布来转化PrintVTable(fa4);//虚表3fa4 = (int*)*((int*)&b + (sizeof(B)+sizeof(C)) / 4 - 3); //根据在内存中的分布来转化PrintVTable(fa4);A* p;p = &a;p->fun1();p->fun2();p = &b;p->fun1();p->fun2();p = &c;p->fun1();p->fun2();p = &d;p->fun1();p->fun2();}}#endif</span>

      我这篇博客没有细说,知识将我研究它们关系以及特点的时候的代码给出来了,其实我也准备好好写出来的,我也整理了其中很多的内容,我将它们截图下来了,其中的一些图如下:


1.关于虚表:



2. 菱形普通继承


3.菱形继承,虚基类



4.虚菱形继承




        但是好像古代某位名人去黄鹤楼的时候却发现已经有人在黄鹤楼提过诗了,它发现特别好,于是就没有作诗。其实我也发现了一个总结的挺好的文章,文章是我大学时期最熟悉的人写的,所以我把这篇文章的地址附在下面吧:

                                http://blog.csdn.net/sulijuan66/article/details/48897867

1 0
原创粉丝点击