概念
保持已有类的特性而构造新类的过程称为继承;
在已有类的基础上新增自己的特性而产生新类的过程称为派生;
被继承的已有类称为基类(或父类);
派生出来的新类称为派生类(或子类)。
继承是面向对象程序设计使代码可以复用的重要手段,它允许程序员在保持原有类特性的基础上进行扩展,增加功能。这样产生新的类,称派生类。继承呈现了面向对象程序设计的层次结构,体现了由简单到复杂的认知过程。
示例代码:
class Parent
{
private:
int parent;
public:
Parent()
{}
};
class Child:public Parent
{
public:
Child()
{}
private:
int child;
};
如上面的代码所示,继承的表示方法为子类的名字加冒号再跟访问限定符再加父类的名字。
继承关系和访问限定符
三种访问权限
public:可以被任意实体访问;
protected:只允许子类及本类的成员函数访问;
private:只允许本类的成员函数访问。
三种继承方式
public:不改变基类成员的访问权限;
protect:会将基类中的public成员变为子类的protected成员,其他成员的访问权限不变;
private:使基类所有成员在子类中的访问权限变为private。
注意:在使用class关键字时默认的继承方式使private,使用struct时的默认继承方式使public,最好显式写出继承方式。
派生类中的默认成员函数
继承关系中,如果派生类没有显式的定义:
1.构造函数;
2.拷贝构造函数;
3.析构函数;
4赋值操作符重载;
5.取地址操作符函数;
6.const修饰的取地址操作符重载;
编译系统则会默认合成这六个默认的成员函数。
继承关系中构造函数调用顺序
注意:
1.基类没有缺省构造函数,派生类必须在初始化列表中显式给出基类名和参数列表。
2.基类没有定义构造函数,则派生类也可以不用定义,全部使用缺省构造函数。
3.基类定义了带有形参表构造函数,派生类就要一定定义构造函数。
继承关系中析构函数调用过程
示例代码:
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
class Parent
{
private:
int parent;
public:
Parent()
{
cout << "Parent()" << endl;
}
~Parent()
{
cout << "~Parent()" << endl;
}
void FunTest()
{
cout << "FunTest" << endl;
}
};
class Child:public Parent
{
protected:
int child;
Parent P1;
public:
Child()
{
P1;
cout << "Child()" << endl;
}
~Child()
{
cout << "~Child()" << endl;
}
};
int main()
{
Child C1;
return 0;
}
如上图所示代码,运行结果如图
继承体系中的作用域
1.在继承体系中的基类和派生类是两个不同作用域;
2.基类和派生类中有同名成员时,派生类将屏蔽基类对成员的直接访问。(在子类成员函数中,可以使用形如 “基类::基类成员” 访问)
注意:在实际中继承体系里最好不要定义同名的成员。
继承中赋值兼容规则
1.子类对象可以赋值给父类对象(切割/切片);
2.父类对象不能赋值给子类对象;
3.父类的指针/引用可以指向子类对象;
4.子类的指针/引用不能指向父类对象(可以通过强转);
解释:子类继承父类,它含有父类的部分,并对其进行扩充。子类对象给父类对象赋值,实际就是子类对象中继承自父类的部分赋值给父类对象,不存在问题。
相反,如果父类给子类赋值,如果子类变量去访问扩充的成员变量,就可能访问不到,造成内存越界。
如图:
友元与继承
友元关系不能继承,也就是说基类友元不能访问子类私有和保护成员。
继承与静态成员
基类定义了static成员,则整个继承体系里面只有一个这样的成员。无论派生出多少个子类,都只有一个static成员实例。
实例代码:
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
class Parent
{
private:
int parent;
public:
Parent()
{
++_count;
}
void FunTest1()
{
cout << "FunTest1" << endl;
}
static int _count;
};
int Parent::_count = 0;
class Child1:public Parent
{
protected:
int child1;
void FunTest2()
{
cout << "FunTest2" << endl;
}
public:
Child1()
{}
};
class Child2 :public Parent
{
protected:
int child2;
void FunTest3()
{
cout << "FunTest3" << endl;
}
public:
Child2()
{}
};
int main()
{
Parent P1;
Child1 C1;
Child2 C2;
cout << P1._count << endl;
return 0;
}
运行结果为3。