C++——继承相关概念

本文详细介绍了 C++ 中的继承概念,包括继承的方式、作用域、成员函数的行为以及继承与友元、静态成员的关系等内容,并探讨了菱形继承和继承与组合的区别。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

1、继承的概念和定义

继承关系和访问限定符

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

2、基类和派生类对象赋值转换

3、继承中的作用域

4、派生类的默认成员函数

(1)构造函数

(2)拷贝构造

(3)赋值运算符

(4)析构

5、继承与友元、继承与静态成员

6、菱形继承

7、继承和组合


1、继承的概念和定义

继承是面向对象程序设计使代码可以复用的最重要的手段,继承是类设计层次的复用

例如:

class person
{
public:
	void print()
	{
		cout << "name:" << _name << endl;
		cout << "age:" << _age << endl;
	}
protected:
	string _name = "peter"; // 姓名
	int _age = 18; // 年龄
};

class student : public person
{
protected:
		int _stuid; // 学号
};
class teacher : public person
{
protected:
	int _jobid; // 工号
};

其中,person是基类,也称为父类;student是派生类,也称子类

继承关系和访问限定符

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

(1)基类private成员在派生类中无论以什么方式继承都是不可见的

不可见:基类的私有成员还是被继承到了派生类的对象中,但是语法上限制派生类对象不管在类内或者类外都不能去访问

举例:person中的私有成员_id在student中不可见,但是已经被student继承

(2)基类private成员在派生类中不能被访问,如果基类成员不想在类外直接被访问,但需要在派生类中能访问,就定义为protected

(3)关键字class默认的继承方式是private,struct默认继承方式是public

2、基类和派生类对象赋值转换

  • 子类向父类的转换叫做切片(子类赋值给父类的对象/父类的指针/父类的引用)

  • 父类对象不能赋值给子类对象

  • 父类的指针或引用不能直接转换为子类的指针/引用,必须通过强制类型转换,但是这种方式不安全,访问不到子类的新增成员

3、继承中的作用域

(1)继承体系中,基类和派生类都有独立的作用域

(2)子类和父类中有同名成员,子类成员将屏蔽父类对同名成员的直接访问,这种情况叫同名隐藏,如果需要访问父类中同名的成员变量,可以通过制定父类作用域访问

注意:在继承体系里最好不要定义同名的成员

B中的fun和A中的fun不构成重载,因为不是在同一作用域;B中的fun和A中的fun构成隐藏,成员函数满足函数名相同就构成隐藏。

4、派生类的默认成员函数

(1)构造函数

父类构造在子类构造初始化列表处自动调用,先执行父类的构造函数,再执行子类的构造函数的函数体;

如果父类没有默认构造需要显式指定,继承自父类的成员必须调用父类构造完成初始化,不能直接在子类构造中进行初始化

(2)拷贝构造

没有显式定义子类的拷贝构造,指向拷贝构造对象时,子类默认的拷贝构造自动调用父类的拷贝构造;显式定义子类的拷贝构造,指向拷贝构造对象时,子类的拷贝构造自动调用父类的拷贝构造

举例:

当没有显式定义子类的拷贝构造时:

显式定义子类的拷贝构造时:

(3)赋值运算符

子类默认的赋值运算符自动调用父类的赋值运算符;显式定义的子类赋值运算符不会自动调用父类的赋值运算符

子类的operator=和父类的operator=构成同名隐藏

举例:

没有显式定义子类的赋值运算符:

显式定义子类的赋值运算符:

在子类赋值运算符中显式调用父类赋值运算符

(4)析构

子类的析构会自动调用父类的析构

底层编译之后,子类析构与父类析构函数同名,构成同名隐藏,编译器在任何情况下都会自动调用父类的析构函数,不需要在子类析构中显式调用父类析构,会导致父类析构最终会被调用两次

5、继承与友元、继承与静态成员

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

基类定义了static静态成员,则整个继承体系里面只有一个这样的成员

6、菱形继承

单继承:一个子类只有一个直接父类

多继承:一个子类有两个或两个以上直接父类

菱形继承是多继承的一种特殊情况

举例:

从上面的例子中我们可以看出菱形继承有数据冗余和二义性的问题,在D的对象中,A的成员会有两份

解决办法:虚拟继承(在B和C继承A时使用虚拟继承)

通过B和C的两个指针指向一张表,这张表叫虚基表,这两个指针叫虚基表指针。

虚基表中存的是偏移量,通过偏移量可以找到下面的A

7、继承和组合

继承是“是”的关系,每个派生类对象都是一个基类对象

组合是“包含”的关系,假如B组合了A,那么每个B对象中都有一个A对象

继承允许根据基类的实现来定义派生类的实现。这种通过生成派生类的复用通常被称为白箱复用

对象组合要求被组合的对象具有良好定义的接口。这种复用风格被称为黑箱复用,组合类之间没有很强的依赖关系,耦合度低。

优先使用对象组合

组合举例:

继承举例:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值