1. 继承机制是面向对象程序设计使代码可以复用的最重要的手段,它允许程序员在保持原有类性质的基础上进行扩展,增加功能。

  2. 继承的定义的格式:

    class 派生类名:继承类型 基类名

    继承类型包括有:public(公有继承)

                    private(私有继承)

                    protected(保护继承)

  3. 继承关系基类的public成员
    基类的private成员
    基    类    的protected成员
    继承引起的访问控制变化
    publicpublic成员
    不可见protected成员非私有成员在子类中的访问属性不变
    privateprivate成员不可见
    private成员非私有成员在子类中的访问属性变为private属性
    protectedprotected成员不可见
    protected成员非私有成员在子类中的访问属性变为protected属性

    举例:


#include <iostream>
using namespace std;
class A
{
public:
	int f1();
private:
	int i1;
protected:
	int j1;
};

int A::f1()
{
	cout << "函数f1的实现" << endl;
}

class B :public A
{
public:
	int f2()
	{
		j1 = 0;
		i1 = 0;
		cout << "函数f2的实现" << endl;

	}	



wKioL1cLJTmzCnBGAABz9WRMrMI523.png在公有继承的子类中,不能访问基类中的private成员。因为基类和子类是两个不同的类域,private成员只能在类能访问。

私有继承和保护继承也是一样。

注意:不管是哪种继承方式,在派生类中都可以访问基类的公有成员和保护成员,基类的私有成员存在,但在子类中不能访问。


4. 关键字class继承时,缺省继承类型则默认为:private.

   关键字struct继承时,缺省继承类型则默认为:public.

5. 继承关系中构造函数的调用顺序:

   基类构造函数------>派生类中对象的构造函数--------->派生类构造函数体

举例:

#include <iostream>
using namespace std;
class A
{
public:
	A()
	{
		a = 0;
		cout << "A's default constuctor called." << endl;
	}
private:
	int a;
};

class B :public A
{
public:
	B()
	{
		b = 0;
		cout << "B's default constuctor called." << endl;
	}
private:
	int b;
};
int main()
{
	B bb;
	system("pause");
	return 0;
}


wKiom1cLKm6zHd5cAAAsw3TQqB0099.png

6. 继承关系中析构函数的调用顺序:

派生类析构函数体------>派生类对中析构函数--------->基类构造函数

说明:

  1. 基类没有缺省构造函数,派生类必须要在初始化列表中显式给出基类名和参数列表;

  2. 基类没有定义构造函数,则派生类也可以不用定义,全部使用缺省构造函数;

  3. 基类定义了带有形参表构造函数,派生类就一定定义构造函数。


7.关于继承体系中的作用域:

在继承体系中基类和派生类是两个不同的作用域,如果子类中有与基类同名的成员,子类成员屏蔽基类对成员直接访问。

注:在子类成员函数中,可以使用 基类名::基类成员名   这样的方式类访问。

举例:

#include <iostream>
using namespace std;
class A
{
public:
	int temp;
private:
	int a;
};

class B :public A
{
public:
	int temp;
	int add()
	{
		temp = 100;
		A::temp = 0;
		return temp;
	}
	
private:
	int b;
	
};
int main()
{
	B bb;
	int ret = 0;
	ret = bb.add();
	system("pause");
	return 0;
}

wKiom1cLMNLAtlMGAAAmy22jHgg514.png

将子类B中的temp赋值为100,基类中的temp赋值为0;

8. 继承中的赋值兼容规则:

   子类对象可以赋值给基类对象,反之不可以;

   基类对象的指针/引用可以指向基类对象,子类对象的指针/引用可以通过强制类型转换的方式指向基    类对象,但是有内存泄漏的风险。

9. 友元与继承

   友元关系不能继承,基类的友元不能访问子类的私有和保护成员。

举例:

#include <iostream>
using namespace std;
class A
{
	friend class C;
public:
	int temp;
private:
	int a;
};

class B :public A
{
public:
	int temp;
private:
	int b;
protected:
	int i;
};

class C
{
public:
	int c;
	int f()
	{
		temp = 2;
		i = 0;
		return 0;
	}
};

int main()
{
	C bb;
	int ret = 0;
	ret = bb.f();
	system("pause");
	return 0;
}

wKioL1cLNGDzCzD9AABy8wIiKgU019.png10. 单继承:一个子类只有一个基类

11. 多继承:一个子类有多个基类,

            定义形式:class 子类名:继承类型 基类名<,继承类型 基类名,继承类型 基类名,...>

12. 菱形继承:

            定义形式:

            举例:

                 wKioL1cLNbXzjyJvAAAzrmi1vU0992.png发现问题:Assistant的对象中存在两份Person成员,菱形继承中存在二义性和数据冗余的问题。

wKioL1cLNkvRmwEHAABf4yT7Azw510.png

虚继承可以解决了菱形继承中二义性和数据冗余的问题,但是一般不适用虚继承,因为虚继承带来了性能上的损耗。

说明:C++语言规定,虚基类子对象是由最派生类的构造函数通过调用虚基类的构造函数进行初始化的。如果一个派生类有一个直接或间接的虚基类,那么派生类的构造函数的成员初始列表中必须列出对虚基类构造函数的调用;如果未列出,则表示使用该虚基类的默认构造函数来初始化派生类对象中的虚基类子对象。