C++之继承
继承允许我们基于已有的类(基类)创建新类(派生类)。派生类自动获得基类的成员(属性和方法),并可以扩展新的功能。继承(inheritance)机制是⾯向对象程序设计使代码可以复⽤的最重要的⼿段,它允许我们在保持原有类特性的基础上进⾏扩展,增加⽅法(成员函数)和属性(成员变量),这样产⽣新的类,称派⽣类。继承呈现了⾯向对象程序设计的层次结构,体现了由简单到复杂的认知过程。代码语言:javascrip
一.继承的概念和定义
1.1继承的概念
继承允许我们基于已有的类(基类)创建新类(派生类)。派生类自动获得基类的成员(属性和方法),并可以扩展新的功能。 继承(inheritance)机制是⾯向对象程序设计使代码可以复⽤的最重要的⼿段,它允许我们在保持原有类特性的基础上进⾏扩展,增加⽅法(成员函数)和属性(成员变量),这样产⽣新的类,称派⽣类。继承呈现了⾯向对象程序设计的层次结构,体现了由简单到复杂的认知过程。
代码语言:javascript
AI代码解释
class Person
{
public:
void identity()
{
cout << "void identity()" <<_name<< endl;
}
protected:
string _name = "张三"; // 姓名
string _address; // 地址
string _tel; // 电话
int _age = 18; // 年龄
};
class Student : public Person
{
public:
protected:
int _stuid; // 学号
};
class Teacher : public Person
{
protected:
string title; // 职称
};
int main()
{
Student s;
Teacher t;
s.identity();
t.identity();
return 0;
}
继承后父类的Person的成员(成员函数+成员变量)都会变成子类的一部分。这里体现出了Student和Teacher复用了Person的成员。
1.2继承的定义
1.2.1定义格式
下⾯我们看到Person是基类,也称作⽗类。Student是派⽣类,也称作⼦类。(既叫基类/派⽣类,也叫⽗类/⼦类)

在这里插入图片描述
继承方式和访问限定符:

在这里插入图片描述
三种继承方式:public、protected 与 private C++ 提供三种继承方式,每种方式对基类成员在派生类中的访问权限有不同影响,同时也决定了派生类对象对基类成员的可访问性:
- public 继承:保持接口一致性 当使用public继承时,基类的public成员在派生类中仍为public,protected成员仍为protected,private成员不可访问。这种继承方式最符合 “is-a” 关系,派生类完全继承基类的接口,外部代码可以像使用基类对象一样使用派生类对象(里氏替换原则)。
- protected 继承:限制接口暴露范围 protected继承会将基类的public成员变为protected,protected成员保持不变,private成员不可访问。此时派生类的子类可以访问这些成员,但外部代码无法直接访问,常用于基类作为 “实现细节” 而非 “接口” 的场景。
- private 继承:实现细节的封装 private继承会将基类的public和protected成员都变为private,仅在派生类内部可访问,外部代码和派生类的子类都无法访问。
继承基类访问方式的变化:
|
基类成员\继承方式 |
public继承 |
protected继承 |
private继承 |
|---|---|---|---|
|
基类的public成员 |
派生类的public成员 |
派生类的protected成员 |
派生类的private成员 |
|
基类的protected成员 |
派生类的protected成员 |
派生类的protected成员 |
派生类的private成员 |
|
基类的private成员 |
在派生类中不可见 |
在派生类中不可见 |
在派生类中不可见 |
- 基类的private成员在派生类中无论以什么方式继承都是不可见的。这里的不可见是指基类的私有成员还是被继承到了派生类对象,但是语法上限制派生类对象无论是在类里面还是在类外面都不可以访问基类的私有成员。这个基类的private成员跟派生类中原有的private成员不同,派生类原有的private成员在类里面可以访问,在类外不可访问
- 由于基类的private成员在派生类中是不能访问的,所以如果基类的成员不想在派生类继承后在派生类的类外面直接访问,但可以在派生类的类里面进行访问,那么就将基类的成员定义为protected成员(protected成员在基类中的里面可以访问,在基类的外面不可以访问)。由此可见protected保护成员限定符是因为继承才出现的
- 总结一下表格,在基类中的private私有成员无论是以什么方式被派生类继承,其在派生类中都是不可见的,基类其它成员在派生类的访问方式是取后面两个的关键字权限小的那一个(成员在基类的访问限定符,继承方式),关键字权限大小关系:public>protected>private
- 如果不加继承方式,那么使用关键字class时,默认继承方式是private继承。使用关键字struct时,默认继承方式是public继承。不过在实际的使用中最好显示写出继承方式
- 在实际的使用场景中,使用最多的是public继承,而protected/private继承的使用场景非常少。同时我们同样不建议使用protected/private继承,因protected/private继承进行继承下来的成员,只能在派生类的类里面进行使用,可维护性不强
二.基类和派⽣类间的转换
- public继承的派⽣类对象可以赋值给基类的指针/基类的引⽤。这⾥有个形象的说法叫切⽚或者切割。寓意把派⽣类中基类那部分切出来,基类指针或引⽤指向的是派⽣类中切出来的基类那部分。
- 基类对象不能赋值给派⽣类对象。
- 基类的指针或者引⽤可以通过强制类型转换赋值给派⽣类的指针或者引⽤。但是必须是基类的指针是指向派⽣类对象时才是安全的。
代码语言:javascript
AI代码解释
class Person
{
protected:
string _name; // 姓名
string _sex; // 性别
int _age; // 年龄
};
class Student : public Person
{
public:
int _Stuid; // 学号
};
int main()
{
//以前我们所知道的强制类型转化
double d = 1.1;
int i = d;
//子类对象可以赋值给父类对象/指针/引用
Student sobj;
Person pobj = sobj;
Person* pp = &sobj;
Person& rp = sobj;
//基类对象不能赋值给派生类对象
//sobj = pobj;
}
2.1切片现象的产生
切片现象通常发生在对象赋值或函数参数传递时,当派生类对象被赋值给基类对象,或者派生类对象被传递给以基类对象为参数的函数时,派生类对象的额外成员变量会被截断,仅保留基类部分的数据。这种现象被称为“切片”。
更多推荐

所有评论(0)