继承
本文将介绍C++面向对象中三大特性之一的继承,并详细介绍多继承引发的菱形继承及其解决方法。
继承的概念及定义
概念
就像现实世界中子辈继承父辈遗产一样,面向对象的语言一样有继承,这是面向对象程序设计使代码可以复用的最重要的手段。
举个例子,老师和学生都是人,都有人的属性,有姓名,年龄,性别等等公共属性,而如果设计这些对象时在类中都定义相关变量,就会造成数据冗余。所以我们可以将这些共同属性统一为一个类Person,再让Student和Teacher两个类去继承Person即可,表现到代码则为:
class Person
{
public:
void Print()
{
cout << "姓名" << _name << endl;
cout << "年龄" << _age << endl;
}
protected:
string _name;
int _age;
};
class Student : public Person
{
public:
void f()
{
Print();
cout << "学号" << _stuID << endl;
}
private:
string _stuID;
};
class Teacher : public Person
{
public:
void f()
{
Print();
cout << "教工号" << _teachID << endl;
}
private:
string _teachID;
};
定义
从上面我们可以知道继承的定义格式:
继承关系与访问限定符:
继承基类成员访问方式的变化:
类成员/继承方式 | public继承 | protected继承 | private继承 |
---|---|---|---|
基类的public成员 | 派生类的public成员 | 派生类的protected成员 | 派生类的private成 员 |
基类的protected成 员 | 派生类的protected成员 | 派生类的protected成员 | 派生类的private成 员 |
基类的private成员 | 在派生类中不可见 | 在派生类中不可见 | 在派生类中不可见 |
·上面的表格简单来说就是除了private成员,其他成员访问权限为继承方式和访问限定符中较小的那个权限;其次,这里的不可见是指成员依旧被派生类继承了,但只是派生类对象无论在类中或类外都不能对其访问。
·但是在实际运用中一般使用都是public继承,几乎很少使用protetced/private继承,也不提倡使用protetced/private继承,因为protetced/private继承下来的成员都只能在派生类的类里面使用,实际中扩展维护性不强。
·使用关键字class时默认的继承方式是private,使用struct时默认的继承方式是public,不过最好显示的写出继承方式。
基类和派生类
基类和派生类对象的赋值类型转换
对于基类和派生类对象的赋值类型转换,简单来说就是将派生类中属于基类的部分付给基类对象,同样作用于指针和引用。这种行为被称为切片或切割。
但是这种赋值只能是派生类赋给基类,而基类对象不能赋给派生类,基类的指针可以通过强制类型转换赋值给派生类,但是需要使用后面介绍的dynamic_cast
来进行识别后进行安全转换。
int main()
{
Person ps;
Student sd;
//1.子类对象可以赋值给父类对象/指针/引用
ps = sd;
Person* pps = &sd;
Person& rps = sd;
//2.基类对象不能赋值给派生类对象
sd = ps;//error
//3.基类的指针可以通过强制类型转换赋值给派生类的指针
//最好用dynamic_cast进行转换,这样才安全
Student* psd = (Student*)&ps;
return 0;