[C++]继承

一.继承的基本概念

  继承是面向对象编程(OOP)中的一个核心特性。它允许我们从一个已经存在的类(父类)创建新类(子类),子类可以继承父类的属性和方法,从而实现代码复用。
  父类(基类):提供属性和方法的类。
  子类(派生类):从父类继承并可能扩展或修改其功能的类。
使用继承,可以减少代码的冗余
形如:

class person
{
protected:
	int _ID;
	int _age;
};
class stu :public person
{
public:
	int _grade;
};

请添加图片描述

1.继承方式和访问限定符

继承方式和访问限定符皆由 public,private,protected 构成,但是不同的继承方式和访问限定符的组合会导致不同的访问方式
ps:protected 表示外部不可访问,而继承的可以访问

继承方式\访问限定符publicprivateprotected
publicpublicprivateprotected
privateprivateprivateprivate
protectedprotectedprivateprotected

其实概括起来就一句话,谁”约束最大“就是谁(private约束最大)。
在实际运用中一般使用都是public继承,几乎很少使用protetced/private继承。

2.基类与派生类的互相赋值

基类是可以直接接受派生类的赋值的,很好理解,这是一个裁剪的过程请添加图片描述
C++允许这样裁剪过来,但是不允许基类裁剪到派生类。
允许指针的转换
派生类的指针 = 基类的指针
那么如下的语法是否可行呢:基类的指针=派生类的指针?

class person{
	int _b;
}
class stu : public person{
	int _a;
}
int main(){
person a;
person* tmp =&a;
stu* tmp2 = (stu*)tmp;
}

在强转的情况下,基类的指针=派生类的指针。

3.继承中的作用域

  在继承体系之中,基类和派生类的作用域有些许区别。
  1.当基类和派生类的成员有相同名称的成员时,优先访问派生类的成员,基类的成员被隐藏,需要加上作用域才行,如person::_a进行显示访问。
  2.在实际的工程之中应当避免使用同名的成员。

4.派生类的6个默认成员函数

  在继承之中,基类与派生类的6个默认成员函数是如何互动的

#include <iostream>
using namespace std;
class person
{
protected:
	person(int a,int b):_ID(a),_age(b){}
	person(const person& x) {
		_ID = x._ID;
		_age = x._age;
	}
	person operator=(const person& x) {
		_age = x._age;
		_ID = x._ID;
		return *this;
	}
	int _ID;
	int _age;
};
class stu :public person
{
public:
	stu(int a,int b, int c):person(a,b),_grade(c){}
	stu(const stu& x):person(x){//在初始化列表调用基类的拷贝构造//直接运用裁剪;
		_grade = x._grade;
	}
	stu operator =(const stu& x) {
		_grade = x._grade;
		person::operator=(x);//裁剪
		return *this;
	}
	~stu() {
		//析构不用写基类的析构
	}
	int _grade;
};
int main()
{
	
	
	return 0;
}

如何创造一个无法被继承的类呢?–将构造或析构给private起来,也就无法被调用了。
ps:继承是无法继承友元函数的
ps:继承的静态成员变量始终一个。

二.棱形继承

有普通的单继承,就有复杂的多继承。
有复杂的多继承就有更复杂的棱形继承。
CPP的缺陷之一也就来源于此。

请添加图片描述
可能会造成如下的问题:
1父类成员重复继承:子类可能会重复继承父类的同一个成员,导致不确定性。
2父类构造函数重复调用:如果不同的路径都调用了父类的构造函数,那么父类的
3构造函数会被调用多次,可能导致资源初始化的问题。
4调用父类方法的冲突:子类通过多条路径继承了父类的方法,可能会产生方法调用冲突。
代码会非常冗杂,并且会产生多重含义,模糊含义。(因为两个基类又继承了同一个基类,他们同一个基类但是会存储在不同的位置,有着不同的值,造成多义性)

1.如何解决

——————使用虚拟继承————————
CPP为了解决这种情况,开发了虚拟继承的方式。
两个基类继承的基类在同一片区域。
如下

class high {
public:
	int h;
};
class mid_1 : virtual public high
{
public:
	int m1;
};
class mid_2 : virtual public high {
public:
	int m2;
};
class lat :public mid_2, public mid_1
{
public:
	int l;
};
int main()
{
	lat tmp;
	tmp.l = 1;
	tmp.m1 = 2;
	tmp.m2 = 3;
	tmp.mid_2::h = 100;
	tmp.mid_1::h = 200;

	return 0;
}

请添加图片描述

三.总结

继承与组合之间的关系:
继承是一个“is”
组合时一个“has”
继承在逻辑上表示它是什么,组合在逻辑上表示它有什么。
继承是一个”白箱操作“,组合是一个“黑箱操作”,继承可以清晰的看到内部有啥,而组合因为其类的封装,我们只需使用即可
继承的耦合度高,组合的耦合度低。
在一般情况下应该 多多使用组合而非继承

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值