知识点2【多继承】
多继承:一个子类 继承多个父类。
class 子类名:继承方式1 父类1,继承方式2 父类2,....
{
//子类新增的数据
}
1、子类和父类的构造与析构顺序
构造顺序:先父类 后子类,多个父类的构造顺序 由子类继承的顺序决定。 析构顺序相反。
#include <iostream>
using namespace std;
class Base1
{
public:
int a;
public:
Base1()
{
a=0;
cout<<"Base1的无参构造 a="<<a<<endl;
}
Base1(int a)
{
this->a=a;
cout<<"Base1的有参构造 a="<<a<<endl;
}
~Base1()
{
cout<<"Base1的析构函数 a="<<a<<endl;
}
};
class Base2
{
public:
int a;
public:
Base2()
{
a=0;
cout<<"Base2的无参构造 a="<<a<<endl;
}
Base2(int a)
{
this->a=a;
cout<<"Base2的有参构造 a="<<a<<endl;
}
~Base2()
{
cout<<"Base2的析构函数 a="<<a<<endl;
}
};
class Son:public Base1, public Base2
{
public:
int a;
public:
Son()
{
a=0;
cout<<"Son的无参构造 a="<<a<<endl;
}
Son(int a,int b, int c):Base1(a),Base2(b)
{
this->a=c;
cout<<"Son的有参构造 a="<<this->a<<endl;
}
~Son()
{
cout<<"Son的析构函数 a="<<a<<endl;
}
};
int main(int argc, char *argv[])
{
Son ob1(10,20,30);
return 0;
}
2、子类和父类的同名处理(加父类作用域)
子类和父类的数据成员同名,子类优先使用自身数据,如果调各自父类的同名成员 加父类的作用域。
子类和父类的函数成员同名,子类的函数 会屏蔽 任何父类的所有同名函数。(加父类的作用域)
#include <iostream>
using namespace std;
class Base1
{
public:
int a;
public:
Base1()
{
a=0;
cout<<"Base1的无参构造 a="<<a<<endl;
}
Base1(int a)
{
this->a=a;
cout<<"Base1的有参构造 a="<<a<<endl;
}
~Base1()
{
cout<<"Base1的析构函数 a="<<a<<endl;
}
void func(void)
{
cout<<"Base1 func void"<<endl;
}
};
class Base2
{
public:
int a;
public:
Base2()
{
a=0;
cout<<"Base2的无参构造 a="<<a<<endl;
}
Base2(int a)
{
this->a=a;
cout<<"Base2的有参构造 a="<<a<<endl;
}
~Base2()
{
cout<<"Base2的析构函数 a="<<a<<endl;
}
void func(void)
{
cout<<"Base2 func void"<<endl;
}
void func(int)
{
cout<<"Base2 func int"<<endl;
}
};
class Son:public Base1, public Base2
{
public:
int a;
public:
Son()
{
a=0;
cout<<"Son的无参构造 a="<<a<<endl;
}
Son(int a,int b, int c):Base1(a),Base2(b)
{
this->a=c;
cout<<"Son的有参构造 a="<<this->a<<endl;
}
~Son()
{
cout<<"Son的析构函数 a="<<a<<endl;
}
void func(void)
{
cout<<"Son func void"<<endl;
}
};
int main(int argc, char *argv[])
{
Son ob1(10,20,30);
cout<<ob1.a<<endl;//30
cout<<ob1.Base1::a<<endl;//10
cout<<ob1.Base2::a<<endl;//20
ob1.func();
ob1.Base1::func();
ob1.Base2::func();
ob1.Base2::func(10);
return 0;
}
知识点3【菱形继承】
菱形继承:有公共祖先的继承,叫菱形继承。
#include <iostream>
using namespace std;
class Animal
{
public:
int a;
};
class Sheep:public Animal{};
class Tuo:public Animal{};
class SheepTuo:public Sheep,public Tuo{};
int main(int argc, char *argv[])
{
SheepTuo ob1;
cout<<ob1.Sheep::a<<endl;
cout<<ob1.Tuo::a<<endl;
return 0;
}
知识点4【虚继承】
继承的时候 需要加上关键字virtual。能保证子类只会拥有一份公共祖先的数据。
cl /d1 reportSingleClassLayoutAnimal main.cpp
1、菱形继承的内存布局
Animal类的布局:
Sheep类的布局:
Tuo类的布局:
SheepTuo类的布局:
2、虚继承的内存布局
#include <iostream>
using namespace std;
class Animal
{
public:
int a;
};
class Sheep :virtual public Animal {};
class Tuo :virtual public Animal {};
class SheepTuo :public Sheep, public Tuo {};
int main(int argc, char* argv[])
{
SheepTuo ob1;
ob1.a = 100;
int off_set = *((int*)(*(int*)(&ob1)) + 1);
cout << off_set << endl;
cout << *(int*)((char*)(&ob1) + off_set) << endl;
return 0;
}
总结:虚继承的原理
如果一个类 virtual继承父类,子类就会产生一个虚基类指针(vbptr)指向虚基类表(vbtable),而vbtable存储的是通过vbptr访问公共数据的偏移量。