C++:继承
一、继承的概念及定义
1.1 继承的概念
继承(inheritance)机制是面向对象程序设计使代码可以复用的最重要的手段之一。
继承是在已有类的基础上派生出新类,新类可以在保持原有类特性的基础上进行扩展,增加新的属性和方法。原有类被称为父类、基类;新类被称为子类或派生类!继承可以提高代码的复用性,呈现出面对面向对象程序设计的层次结构。
【实例】:
class Person
{
public:
void Print()
{
cout << "name:" << _name << endl;
cout << "age:" << _age << endl;
}
protected:
string _name = "peter"; // 姓名
int _age = 18; // 年龄
};
// 继承后父类的Person的成员函数和成员变量都变成子类的一部分
class Student : public Person
{
protected:
int _stuid; // 学号
};
int main()
{
Student s;
s.Print();
return 0;
}
1.2 继承格式和继承属性
1)、 继承格式
下面我们看到Person是父类,也称作基类。Student是子类,也称作派生类。继承方式和访问限定符一样,有三种:public继承、protected继承、private继承!
2)、继承关系和访问方式变化
继承和访问限定符分类如下:
继承方式的不同,必然会导致访问方式的变化,具体如下:
类成员/继承方式 | public继承 | protected继承 | private继承 |
---|---|---|---|
基类的public成员 | 派生类的public成员 | 派生类的protected成员 | 派生类的private成员 |
基类的protected成员 | 派生类的protected成员 | 派生类的protected成员 | 派生类的private成员 |
基类的private成员 | 在派生类中不可见 | 在派生类中不可见 | 在派生类中不可见 |
- 基类private成员在派生类中无论以什么方式继承都是不可见的。这里的不可见是指基类的私有成员还是被继承到了派生类对象中,但是语法上限制派生类对象不管在类里面还是类外面都不能去访问它。
- 基类private成员在派生类中是不能被访问,如果基类成员不想在类外直接被访问,但需要在派生类中能访问,就定义为protected。保护成员限定符是因继承才出现的。
- 基类的私有成员无论如何派生类都无法访问,至于其他组合方式,访问方式是基类成员访问限定符和继承方式的较小方式。(public > protected > private)
- 使用关键字class时默认的继承方式是private,使用struct时默认的继承方式是public,不过最好显示的写出继承方式。
.
二、基类和派生类对象赋值转换
相似类型对象支持相互转换,并且中间会生成一个临时变量。比如:int和double都表示数,只是精度的问题罢了,所以支持赋值转换。
【实例】:
int main()
{
//为什么i加引用,不加const会报错.
//原因在于赋值转化时,首先会将变量d转化为int类型并将结果存在一个临时变量里
//所以这里引用绑定的对象实际是这个临时变量,所以必须加const,否则会编译报错。
double d = 1.2;
//int& i = d; //error
const int& i = d;
return 0;
}
但在基类和派生类对象之间的赋值转换不会产生临时变量。子类对象赋值给父类对象/父类指针/父类的引用,我们认为这是天然的,中间不产生临时变量,这个叫做父子类赋值兼容规则(或切割、切片)
- 在public继承中,父类和子类是一个is-a关系。
- 基类对象不能赋值给派生类对象。
- 基类的指针或者引用可以通过强制类型转换赋值给派生类的指针或者引用。但是必须是基类的指针是指向派生类对象时才是安全的。这里基类如果是多态类型,可以使用RTTI(RunTime Type Information)的dynamic_cast 来进行识别后进行安全转换。
【实例验证】
class Person
{
protected:
string _name; // 姓名
string _sex; // 性别
int _age; // 年龄
};
class Student : public Person
{
public:
int _No; // 学号
};
in