什么是继承
比如你创建一个类:叫person
,你的目的是用这个类来存放不同职业的人的年龄,工作,姓名 你可以在这个类中定义以下的成员变量和成员函数:
class Person
{
public:
void Print()
{
cout << "name:" << _name << endl;
cout << "age:" << _age << endl;
}
protected:
string _name = "peter"; // 姓名
int _age = 18; // 年龄
};
这个时候,假如有个学校的校长来让你把他们学校的老师
和同学
的信息存储起来,这个时候就可以用到你的这个person
类了,但是你发现,这个person
类有个缺点,就是老师
有工号
学生有 学号
这是两个不同种类的信息呀,难道要定义在同一个类中吗?
这个时候,一种新的玩法就来了。
你可以单独定义2个类,一个类叫Student
用来存放学生的学号,一个类叫Teacher
用来存放老师的工号,但是呢,学生和老师的有共同特点的信息,比如年龄和姓名之类的可以继续沿用上面person
类的定义,那该怎样写呢?
#include<iostream>
using namespace std;
class Person
{
public:
void Print()
{
cout << "name:" << _name << endl;
cout << "age:" << _age << endl;
}
protected:
string _name = "peter";
int _age = 18;
};
class Student : public Person
{
protected:
int _stuid; // 学号
};
class Teacher : public Person
{
protected:
int _jobid; //工号
};
int main()
{
Student s;
Teacher t;
s.Print();
t.Print();
return 0;
}
上面的这种写法就是 继承
继承的定义
定义的格式
我们可以得出下面的一个表格:
这里,我们来理解一下protected
和 private
在以前,我们认为它们的区别不是那么明显:都是在类外面不能使用,只能在类里面使用。
但是现在,如果我们想定义一个成员变量,这个成员变量可以继承(也就是可以被子类使用)但是只能在子类中使用,不能在类外使用,由于,private
成员变量不能被子类使用,所以我们这个时候可以用protected
总结:
- 基类private成员在派生类中无论以什么方式继承都是不可见的。这里的不可见是指基类的私
有成员还是被继承到了派生类对象中,但是语法上限制派生类对象不管在类里面还是类外面
都不能去访问它。 - 基类private成员在派生类中是不能被访问,如果基类成员不想在类外直接被访问,但需要在
派生类中能访问,就定义为protected。可以看出保护成员限定符是因继承才出现的。 - 实际上面的表格我们进行一下总结会发现,基类的私有成员在子类都是不可见。
基类的其他 成员在子类的访问方式 == Min(成员在基类的访问限定符,继承方式),
public > protected private
。 - 使用关键字class时默认的继承方式是private,使用struct时默认的继承方式是public,不过
最好显示的写出继承方式。 - 在实际运用中一般使用都是public继承,几乎很少使用protetced/private继承,也不提倡
使用protetced/private继承,因为protetced/private继承下来的成员都只能在派生类的类里
面使用,实际中扩展维护性不强
is-a
的关系
不同类型之间的对象赋值的时候,如果是相近的类型可以隐式类型转换,隐式类型转换的话会产生临时变量
但是临时变量具有常性,所以,当你想要这样写时,是错的:
说那么多,就是想说下面的这种情况:
int main()
{
Student s;
Person p = s;
return 0;
}
这个student
类可不可以赋值给Person
类呢?想想我们之前举的例子。
答:可以,
因为他们也是相近的类型,一个person
是父类,一个student
是子类,
所以,在公有继承的前提下,person
和 student
的关系可以比拟成is-a
的关系。
“is-a” 是面向对象编程中描述继承关系的一种概念。它表示一个类(A)
是另一个类(B)的子类
或派生类,也可以说类B
是类A
的父
类或基类。这意味着类A继承了类B的所有属性和方法,同时可以添加自己的属性和方法,以扩展或特化类B的功能。继承关系允许在类之间建立层次结构,使代码重用和扩展更加方便。
例如,如果有一个类 “动物” 和一个类 “狗”,你可以说 “狗 is-a 动物
”,这意味着 “狗” 类继承了 “动物” 类的属性和方法,因为狗是一种动物。这允许你在 “狗” 类中使用 “动物” 类的功能,并在需要时添加独特于狗的属性和方法。
继承关系有助于提高代码的可维护性和可扩展性,因为它允许你在不必重新编写现有代码的情况下创建新的类,并在现有类的基础上构建新的功能。这是面向对象编程中的一个重要概念,有助于组织和抽象复杂的代码结构。
在上面的列子中,Teacher
是人 ,Teachar
is a
Person
, Student
也是人,Student
is a
Person
他们都有人的共同属性,都可以继承Person
类中的属性,并且可以拥有自己的独特的属性。
父类和子类在公有继承的前提下,是
is-a
的关系,注意,公有继承
的前提
这个时候在分析一下下面的写法对不对?
但是就,这种情况一般是子类
赋值给 父类
, 即:父类是子类中父类那一部分属性的别名
不能父类赋值给子类。