继承是面向对象的三大特性之一,下图展示了一些类与类之间的关系。
可以看出来,下层级别的成员除了拥有上一层的共性,还有自己的特性,这个时候就需要考虑用继承的技术以减少重复代码。
继承的语法:
class A: 继承方式 B;
A类称为子类或者派生类,B类称为父类或者基类,子类中的成员包含两个部分,一部分是从父类继承过来的,另一部分是自己增加的成员,从父类继承过来的表现共性,新增的成员体现个性。
class Animal{
public:
void information(){
cout<<"我是一只动物"<<endl;
}
};
class Dog:public Animal{
public:
void dog(){
cout<<"我是一只狗"<<endl;
}
};
class Hashiqi:public Dog{
public:
void hashiqi(){
cout<<"我是一只二哈"<<endl;
}
};
void test01(){
Hashiqi hashiqi;
hashiqi.information();
hashiqi.dog();
hashiqi.hashiqi();
}
继承的方式:
继承方式一共有三种:
公共继承;
保护继承;
私有继承。
继承中的对象模型:
从父类中继承过来的成员,哪些属于子类对象,下面通过一段代码测试一下。
class Base
{
public:
int m_A;
protected:
int m_B;
private:
int m_C; //私有成员只是被隐藏了,但是还是会继承下去
};
//公共继承
class Son :public Base
{
public:
int m_D;
};
void test01()
{
// 结果为sizeof Son =16
cout << "sizeof Son = " << sizeof(Son) << endl;
}
可以看出,父类和子类共有4个int类型的成员,Son类的大小为16,所以得出父类中的私有成员也会被子类继承下去,只是被编译器隐藏了所以才会访问不到。
继承中构造和析构顺序:
子类继承父类后,当创建子类对象时,也会调用父类的构造函数,那么父类和子类构造和析构的顺序是怎样的呢,下面通过一段代码测试一下。
class Base
{
public:
Base(){
cout<<"Base的构造函数"<<endl;
}
~Base(){
cout<<"Base的析构函数"<<endl;
}
};
//公共继承
class Son :public Base
{
public:
Son(){
cout<<"Son构造函数"<<endl;
}
~Son(){
cout<<"Son析构函数"<<endl;
}
};
void test01(){
Son son;
}
执行结果如下图:
可以看出,继承中,先调用父类的构造函数,再调用子类的构造函数,析构顺序与构造顺序相反。
继承同名成员处理方式:
当子类和父类出现同名的成员,怎么通过子类对象,访问子类或者父类中的同名数据呢,有下面三条规则:
1.子类对象可以直接访问到子类中的同名成员;
2.子类对象加作用域可以访问到父类中的同名成员;
3.当子类与父类有同名的成员函数,子类会隐藏父类中同名的成员函数,加作用域可以访问到父类中的同名函数。
下面是一个简单的例子:
class Base{
public:
Base(){
m_a=10;
}
void function(){
cout<<"Base--function的调用"<<endl;
}
public:
int m_a;
};
class Son:public Base{
public:
Son(){
m_a=20;
}
void function(){
cout<<"Son--function的调用"<<endl;
}
public:
int m_a;
};
void test01(){
Son son;
cout<<"Son下的m_a"<<son.m_a<<endl;
cout<<"Base下的m_a"<<son.Base::m_a<<endl;
son.function();
son.Base::function();
}
菱形继承:
概念:两个子类继承同一个父类,又有某个类同时继承这两个子类,这种继承称为菱形继承。
下面是一个菱形继承的例子:
菱形继承带来的问题是子类继承两份相同的数据,导致资源浪费,所以采用虚继承来解决菱形继承带来的问题。
下面是一个简单的例子:
class Animal{
public:
int m_age;
};
class Ma:virtual public Animal{};
class Lv:virtual public Animal{};
class LuoZi:public Ma,public Lv{};
void test01(){
LuoZi luoZi;
luoZi.Ma::m_age=10;
luoZi.Lv::m_age=5;
cout<<luoZi.Ma::m_age<<endl;
cout<<luoZi.Lv::m_age<<endl;
cout<<luoZi.m_age<<endl;
}
来源:CSDN
作者:潘芝
链接:https://blog.csdn.net/m0_37772527/article/details/104537223