【C++】继承(三)

继承(一)https://blog.csdn.net/ly_6699/article/details/88801492
讲到继承的概念和定义,基类和派生类对象赋值转换

继承(二)https://blog.csdn.net/ly_6699/article/details/88805464
讲到继承中的作用域和派生类的默认成员函数

今天,我们接着前两天的内容继续讲继承。本节内容主要有 继承和友元,继承和静态函数,继承和组合

5.继承和友元

这里只需要注意一点,友元关系不能继承! 也就是说:基类的友元不能访问子类的private 和protected 成员。

class Student;      //声明一个类

class Person
{
public:
	friend void Display(const Person & p, const Student&s);
protected:
	string _name;
};
class Student :public Person
{
protected:
	int _No;
};
void Display(const Person& p, const Student& s)
{
	cout << p._name << endl;
	//下面编译不通过,因为基类的友元函数无法访问派生类成员
	cout << s._No << endl;  
}

6. 继承和静态成员

若在基类中定义了static 静态成员,则无论派生出多少子类,整个继承体系内只有一个这样的成员。
例题:计算共创建了多少个对象。

class Person
{
public:
	Person()   { ++_count; }
protected:
	string _name;
public:
	static int _count;   //统计人数
};
int Person::_count = 0;    //静态成员要在类外定义
class Student :public Person
{
protected:
	int _No;
};
class Graduade :public Student
{
protected:
	int _ID;
};
void Test()
{
	Student s1;
	Student s2;
	Student s3;
	Graduade g1;
	cout <<"人数:"<< Person::_count << endl;    //4
	Student::_count = 0;
	cout << "重置后人数:" << Person::_count << endl;     //0
}

由重置后人数为0,即可得出结论:基类中定义的static成员在整个继承体系在只有这一个

7.继承和组合

我们都知道,类复用有三种方式

A.模板:一般是类型的复用
B.继承:常用的public继承是 is-a 关系
C.组合:是一种 has-a的关系

模板的内容我在之前的模板初阶模板进阶 两章博客中中已经讲的很多了,想了解的可以直接点链接去看。这里我就只讲一下继承和组合:

  1. public 继承是一种 is-a 的关系。也就是说每个派生类对象都是一个基类对象。

比如我们平时会说学生是人,所以学生和人两个类间应该是继承关系

  1. 组合是一种 has-a 的关系。假设B组合了A,每个B对象中都有一个A对象。

比如我们说学生有学号,所以学生和学号两个类间应该是组合关系

  1. 我们一般优先使用对象的组合,而不是类的继承。因为对象组合有助于我们保证每个类的封装性(原因是组合使用黑箱复用)。

  2. 继承允许我们根据基类的实现来定义派生类的实现。这种通过生成派生类的复用被称为白箱复用。这里的术语“白箱”是相对可视性而言的:在继承方式中,基类的内部细节对于子类是可见的。但继承在一定程度上破坏了基类的封装性,并且基类的改变对派生类有很大的影响。这里派生类和基类间的依赖关系很强,耦合度很高。

  3. 对象组合也是代码复用的一种方式。对于类外要增加新的更复杂的功能,我们可以通过组装或组合对象来获得。这里对象的组合要求被组合的对象具有良好定义的接口。这种只提供接口的复用被称为黑箱复用。因为对象内部细节是不可见的。 组合类之间没有很强的依赖关系,耦合度低。

  4. 对于较好的软件设计,我们一般要求模块内高内聚,模块间低耦合。所以我们尽量多使用组合,它的耦合度低,代码维护性好。

  5. 组合和继承各有用武之地,博主只是在既可以用继承也可以用组合的情况下更推荐用组合。但是如果有些关系是很明显的 is-a关系,我们就选择用继承,另外如果我们要实现多态也必须用继承。

继承的应用如下:

  //Car和BMW,Benz 构成is-a 的关系  宝马是车,奔驰是车 
class Car
{
protected:
	string _colour = "白色";     //颜色
	string _num = "陕A123";     //车牌号
};
class BMW :public Car
{
public:
	void Drive()
	{
		cout << "简单" << endl;
	}
};
class Benz :public BMW
{
public:
	void Drive()
	{
		cout << "舒适" << endl;
	}
};
void Test1()
{
	Benz car;
	car.Drive();      //舒适
}

组合的应用如下:

//Tire和Car构成has-a 的关系       车有轮胎
class Tire
{
protected:
	string _brand = "Michelin";   //品牌
};
class Car
{
protected:
	string _colour = "白色";    //颜色
	string _num = "陕A123";    //车牌号
	Tire _t;               //轮胎
};

若创建一个对象 Car _c; 由上面代码看到,这里的Car 组合了Tire, 则通过监视窗口可以看到Tire 变成Car 的一部分。
在这里插入图片描述

我暂时就讲到这里啦。有其他更多精彩的内容,我会在之后更新,大家可以多关注我的博客哟~

下篇博客,我会继续讲继承。
继承(四)https://blog.csdn.net/ly_6699/article/details/88858618
讲到复杂的菱形继承和菱形的虚拟继承

猜你喜欢

转载自blog.csdn.net/ly_6699/article/details/88858186