什么是继承?为什么要有继承?怎么继承?
当我们定义一个类后,
class Student
{
public :
void display()
{
cout << "num : " << num << endl;
cout << "name : " << name << endl;
cout << "sex : " << sex << endl;
}
private :
int num;
string name;
char sex;
}
如果学校的某一部门除了需要用到学号,姓名,性别以外,还需要用到年龄,地址等信息
我们可以重新声名一个类class Student1
class Student1
{
public :
void display()
{
cout << "num : " << num << endl; //重复
cout << "name : " << name << endl; //重复
cout << "sex : " << sex << endl; //重复
cout << "age : " << age << endl;
cout << "addr : " << addr << endl;
}
private :
int num; //重复
string name; //重复
char sex; //重复
int age;
string addr;
}
这时我们定义的很多代码 在刚刚我们定义的Student类中 已经定义过了,这时就有一些聪明的小机灵鬼想到,我们是否能够利用原来声明的类Student 作为基础,再加上新的内容即可,减少没有必要的重复操作。
而我们要学习得继承就是为了解决这个问题。
以马为例,“公马”继承类全部马的特征,再加上雄性的新特征,“白公马”又继承了“公马”的全部特征,又加了颜色的特性。公马是马派生出来的一个分支,白公马是公马派生出来的一个分支。
继承:就是再一个已存在的类的基础上建立一个新的类。
基类(Base class),父类(Father class),继承他们的特性的类叫,派生类(Derived)或子类(Son class)
单继承:一个派生类只从一个基类派生
多继承:一个派生类可以从多个基类派生。
一。派生类的声名方式
class Student1 : public Student //共有继承 声名基类是Student
{
public :
void display_1()
{
cout << "age : " << age << endl;
cout << "addr : " << addr << endl;
}
private :
int age; //新增成员函数
string addr; //新增成员函数
}
class 派生类名:【继承方式】 基类名
{
派生类新增成员。
}
继承方式有 public (共有) ,private (私有),protected(保护).
二。派生类的构成
(1)从基类接受所有成员,不能只要一部分,但是无法继承friend函数和构造函数析构函数,new生成的成员。
缺点,有些基类的成员在派生类中是用不到的,但是也必须继承,这就造成了数据冗余。
(2)调整从基类接收的成员。就是改变基类成员在派生类中的访问属性(通过继承方式决定)。还可以再派生类中声明一个与基类成员同名的成员,则派生类中的新成员会覆盖基类的同名成员,但是应该注意,如果是成员函数,不仅应使函数名相同,而函数的参数表(参数的个数和类型)也应相同。如果不相同就变成的函数重载了,而不是函数的覆盖。
三。派生类的成员的访问属性
共有继承
公用类在派生类中的访问属性 | ||
---|---|---|
在基类中的访问属性 | 继承方式 | 在派生类中的访问属性 |
private | public | 不可访问 |
public | public | public |
protected | public | protected |
派生类无法直接调用基类中的私有成员,但是可以通过基类中的public函数或 protected函数来访问基类中的私有成员
私有继承
私有基类在派生类中的访问属性 | ||
---|---|---|
在基类的访问属性 | 继承方式 | 在派生类中的访问属性 |
private | private | 不可访问 |
public | private | private |
protected | private | private |
既然声名为私有继承就表示,将原来能被外界访问的成员隐藏起来,基类的private还是不能访问,还是只能通过基类中的pubic 或 protected 来访问,而基类中的protected 和 public 中的成员 变成了private 存在了 派生类内。类外就不能访问了。
(1)不能通过派生类对象引用从私有基类继承过来的任何成员
(2)派生类的成员函数不能访问私有基类的私有成员,但是可以访问私有基类的公有成员。
保护继承
保护成员不能被类外引用,可以被派生类的成员函数引用。
前面将友元比喻成朋友,可以允许好朋友进入自己的卧室,而保护成员相当与保险箱,任何外人都不能窥视,只有子女才能打开。
特点:保护基类的共有成员和保护成员在派生类中都成了保护成员,其私有成员仍为基类私有。
保护基类在派生类中的访问属性 | ||
基类中的访问属性 | 继承方式 | 派生类中的访问属性 |
private | protected | 不可访问 |
public | protected | protected |
protected | protected | protected |
比较一下私有继承和保护继承:
在直接派生类中,以上两种继承方式相同:在类外不能访问任何成员而在派生类中可以通过成员函数访问基类中的公用成员和保护成员。但是如果继续派生,在新的派生类中两种继承方式的作用就不同了。例如,如果以公用的继承方式派生出一个新派生类,原来私有基类中的成员在新的派生类中都成了不可访问的成员,无论在派生类内还是在派生类内都不能访问,而原来保护基类中的公用成员和保护成员在新派生类中为保护成员,可以被新派生类的成员函数访问。
派生类中的4中访问属性:
(1)公用的,派生类内类外都可以访问
(2)受保护的,派生类内可以访问,派生类外不能访问,其下一层的派生类可以访问。
(3)私有的,派生类内可以访问,派生类外不能访问。
(4)不可访问的,派生类内外都不能访问。
派生类中的成员访问属性 | |||
---|---|---|---|
派生类中的访问属性 | 在派生类中 | 在派生类外 | 在下层派生类中 |
公用 | 可以 | 可以 | 可以 |
保护 | 可以 | 不可以 | 可以 |
私有 | 可以 | 不可以 | 不可以 |
不可访问 | 不可以 | 不可以 | 不可以 |
然后我们总结一下,这个规律。
谁更厉害: private > protected >public
被继承之后的权限 : public > protected > private.
四。多级派生
这时就出现了 直接派生类和间接派生类,直接基类和间接基类。
多类继承中常采用public
class A
{
public :
int i;
protected :
void f1();
int j;
private :
int k;
};
class B : public A
{
public :
void f2();
protected :
void f3();
private :
int m;
};
class C : protected B
{
public :
void f4();
private :
int n;
};
各成员在不同类中访问属性 | |||||||||
i | f1() | j | k | f2() | f3() | m | f4() | n | |
基类A | 公用 | 保护 | 保护 | 私有 | |||||
公用派生类B | 公用 | 保护 | 保护 | 不可访问 | 公用 | 保护 | 私有 | ||
公用派生类C | 保护 | 保护 | 保护 | 不可访问 | 保护 | 保护 | 不可访问 | 公用 | 私有 |
无论哪一种继承方式,在派生类中是不能访问基类的私有成员的,私有成员只能被本类的成员函数所访问,毕竟派生类与基类不是同一类。
如果在多级派生时都采用公用继承的方式,那么直到最后一级的派生类都能访问基类的公用成员和保护成员。
如果是私有继承方式,经过若干次派生后,基类的所有成员已经变成不可访问的了。
如果采用保护继承方式,在派生类外是无法访问派生类中的任何成员。而且经过多次派生后人们很难记住那些成员可以访问,哪些不可以访问。
所以我们多级继承时常用公用继承。