C++进阶之继承

1 为什么要用继承?

继承是代码的复用的一种实现,呈现了oop的层次结构,继承是类设计层次的复用。

2 继承的风格

class A{};
class B :public A{};

:为继承符号
A为被继承类称为 基类
B为继承类 ,称为派生类
public称为继承方式 :
继承方式分为 public protected private 三种
同样 访问限定符也分为 public protected private 三种

3 继承基类成员访问方式的变化 :

1 基类为 private时 ,派生类不可见
2 基类非private时访问方式选继承方式和访问方式中最高
(不可见的意思,已经继承下来了,但是无法访问)
访问限定符等级 public < protected < private
即 private等级最森严

3使用关键字 class 时默认的 继承方式是 private ;使用struct默认关键字为 public, 最好显示表明继承方式。

4 实际大多用 public 作为继承方式, 几乎很少使用 private / protected作为继承方式,because , 用了他俩就只能在派生类中使用,导致扩展维护性不强

5 派生类对象可以给基类的对象 / 基类的引用 /基类的指针 赋值,但反过来不行。

6 基类的指针要给派生类指针赋值时,需要在基类指针指向派生类对象的前提下 ,再进行强制类型转换,否则不安全哦

4 继承的作用域

派生类中若出现和基类同名的成员时,则会将基类屏蔽掉,优先使用派生类的成员。
要使用基类的成员,需要 基类 ::成员

5 继承与友元

一句话 ,友元关系在继承时不传递

在这里插入图片描述
在这里插入图片描述

#include "iostream"
#include"string"
//#include"windows.h"
using namespace std;
class Student;
class Person 
{
	friend void Display(const Person& p, const Student& s);
protected :
	string _name="小李子";//C++11新玩法的默认值
};
class Student : public Person 
{
protected: 
	string _stuNum;
};
void Display(const Person& p, const Student& s) 
{
	cout << p._name << endl;
	//cout << s.stuNum << endl;//注意这个不可访问 ,因为友元关系继承后在派生类中失效
}

int main() 
{

	Person p;
	Student s;
	Display(p, s);
	system("pause");
	return 0;
}

6 继承与静态成员

一句话 静态成员只存在一份,不管在哪修改或查看效果一样



#include"iostream"
#include"string"
using namespace std;

class Person 
{
public :
	Person() { ++_count; }
private :
		string _name;
public :
static int _count;

//public :
//	void print() 
//	{
//		cout << _count << endl;
//	}
};
 int  Person:: _count = 0;

 class Student :public Person 
 {
 protected :
	 string _stuNum;
 };
 class Graduate//研究生 
 {
 protected: 
	 string _seminarCourse;//研究课程
 };
int main() 
{
	Person s;
	Student a;
	Student b;g
	Student c;
	Student d;
	Graduate g;
	//s.print();
	cout << Person::_count << endl;
	Student::_count = 0;
	cout << Person::_count << endl;//我们发现 static 只存在一份,而且是同步变化的
	system("pause");
	return 0;
}

7复杂的继承与菱形继承

在这里插入图片描述

图片一目了然 ,不多介绍了 ,
菱形继承 存在的问题:数据冗余和二义性,我们采用*虚拟继承来解决

在这里插入图片描述

#include"iostream"
#include"string"
using namespace std;
class Person
{
public:
	string _name;
};
class Student :virtual public Person
{
public :
	void Change() 
	{
		this->_name = " Peter";
		cout << this->_name << endl;
	}
protected:
	int _stuNum;//学号
};
class  Teacher : virtual public Person 
{
public:
	void A() { cout << "hello" << endl; }
protected:
	int _num;//职工号

};

class Assistant :public Student,public Teacher
{
protected: 
	string _course;//主修课程
};
int main ()
{
	Assistant a;
	cout << "A     :" << a._name << endl;
	Student s;
	/*Person p;
	s.Change();*/
	Teacher t;
	//cout << "T     :" << t._name << endl;//我们发现 使用虚拟继承后 两个类没啥关系了
	s._name = "S";
	cout << "S     :"<<s._name << endl;
	a._name = "peter";
	a.A();
	cout << "A     :" << a._name << endl;
	cout << "T     :" << t._name << endl;//我们发现 使用虚拟继承后 本类并不会修改两个父类,但却能调用两个父类的成员
	cout << "S     :" << s._name << endl;
	system("pause");
   return 0;
}

我们发现:虚拟继承可以解决菱形继承的数据冗余和二义性问题;
但需要注意的是 ,虚拟继承不要用在别的地方。

虚拟继承解决数据冗余和二义性的原理:

#include"iostream"
#include"windows.h"
using namespace std;
class A {
public :
	int a;
};
class B : virtual public A 
{
public:
	int b;
}; 
class C : virtual public A
{
public:
	int c;
};
class D : public B, public C
{
public:
	int d;

};
int main() 
{
	D d;
	d.A::a = 1;//这个时候存在两份a  , d中一份 A中一份,互不相同,但d两个a都可以访问
	d.B::b = 2;//b跟a的原理相同
	d.b = 3;
	d.c = 4;
	
	system("pause");
	return 0;
}

在这里插入图片描述
在这里插入图片描述
怎么禁止一个类被继承?
C++98 将构造函数私有化 ,
C++11 使用final ,直接放在 类名后边关键字

总结

:一般不建议设计出多继承,一定不要设计出菱形继承,否则性能和复杂度上都存在问题。
能使用组合,也能使用继承,优先使用组合

发布了90 篇原创文章 · 获赞 13 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/weixin_44030580/article/details/103142795
今日推荐