继承
●当定义一个新的类时,发现该类具备之前某一个类的基本属性及方法时,就可使用继承技术.
●意义:减少代码重复率,增加代码利用率
一、继承对象模型
(1)C++对象中,成员属性与成员函数是分开存储的,对象的内存大小和成员函数没有关系,但是成员函数在逻辑上是属于类的.
(2)继承关系中,子类会继承所有父类的==成员属性以及成员函数.==但是私有属性被继承后被编译器屏蔽,所以私有成员是不能访问的.
(3)继承关系中,先构造父对象、再构造子对象,析构顺序相反.
(4)如果出现子类成员与父类成员同名情况,则父类的成员会被隐藏,对象直接访问的话,访问到的是子类自己的成员。则需要使用作用域符号::
(5)●在继承模型中,父类中的静态成员变量以及静态成员函数,也会被子类的所有对象共享。(static)--à菱形继承
访问子类:
obj . age
访问父类:
obj. Base: :age
代码1):成员属性与成员函数是分开存储
#include <iostream>
using namespace std;
class Data
{
int _data1;
int _data3;
static int _data2; //不占空间
//不占空间
void fun()
{
cout<<"fun"<<endl;
}
};
int Data::_data2=0;
int main(int argc, char *argv[])
{
cout<<"sizeof(Data):"<<sizeof(Data)<<endl;
return 0;
}
代码2):继承关系
#include <iostream>
using namespace std;
class Data
{
private:
int _data1;
protected:
int _data3;
public:
int _data4;
static int _data2;
void fun1()
{
cout << "fun1" << endl;
}
void fun2()
{
cout << "fun2" << endl;
}
};
int Data::_data2 = 0;
class SonData:protected Data
{
public:
void Visit()
{
cout << _data4 << endl;
cout << _data3 << endl;
//cout << _data1 << endl;
cout << _SonData << endl;
}
private:
int _SonData;
};
int main()
{
cout << "sizeof(Data): " << sizeof(Data) << endl;
cout << "sizeof(SonData): " << sizeof(SonData) << endl;
SonData s1;
s1.Visit();
//s1._data4;
return 0;
}
二、多继承
(1)当一个类继承多个类时,被称为多继承关系.
class A: <继承权限> <类名>, <继承权限> <类名>
{
}
●注意:实际开发应该减少多继承方式
代码3):多继承
#include <iostream>
using namespace std;
class Sheep
{
public:
Sheep():s_kind("羊")
{
age=12;
}
int age;
string s_kind;
};
class Cow
{
public:
Cow():c_kind("牛")
{
age=3;
}
int age;
string c_kind;
};
class SiBuXiang:public Sheep,public Cow
{
public:
int age;
};
void test01()
{
SiBuXiang s1;
cout<<s1.c_kind<<endl;
//cout<<s1.age<<endl;
cout<<s1.Sheep::age<<endl;
}
int main(int argc, char *argv[])
{
test01();
return 0;
}
三、虚继承
(1)在多继承基础上,如果多个父类又是继承于同一个父类,那么成员访问就会出现问题,这种继承方式又称菱形继承
代码4):菱形继承
#include <iostream>
using namespace std;
class A
{
public:
static int dataA;
};
int A::dataA=1;
class B:public A
{
};
int main(int argc, char *argv[])
{
B b1;
B b2;
b1.dataA=6;
cout<<b1.dataA<<endl;
cout<<b2.dataA<<endl;
cout<<&(B::dataA)<<endl;
A a1;
a1.dataA=78;
cout<<&(a1.dataA)<<endl;
cout<<&(A::dataA)<<endl;
cout<<a1.dataA<<endl;
cout<<b1.dataA<<endl;
return 0;
}
(2)虚继承方式:
class B:virtual public A
{
}
(3)作用:虚继承不是真正的继承成员属性,而是生成一个虚基类指针(vbptr),该指针可以实现访问同一个属性,而不出现二义性.
(4)原理:虚基类指针vbptr指向一个虚基类表,表中记录了到虚基类中成员变量的偏移量,通过偏移量就能够量就能够正确找到同一个成员变量.
代码4):虚继承
#include <iostream>
using namespace std;
class Animal
{
public:
Animal():age(23)
{
}
int age;
static int n;
};
int Animal::n=10;
class Sheep:virtual public Animal //virtual
{
public:
int SNum;
};
class Cow:virtual public Animal //virtual
{
public:
int CNum;
};
class SiBuXiang:public Cow,public Sheep
{
public:
};
void test01()
{
SiBuXiang s1;
cout<<s1.age<<endl;
cout<<s1.n<<endl; //static 共享
}
void test02()
{
SiBuXiang s2;
s2.age=9;
cout<<s2.age<<endl;
cout<<s2.Sheep::age<<endl;
}
int main(int argc, char *argv[])
{
test01();
test02();
return 0;
}