【C++】继承的基本特性(定义,赋值转换,友元,静态成员,虚拟继承,默认成员函数,作用域)

这篇具有很好参考价值的文章主要介绍了【C++】继承的基本特性(定义,赋值转换,友元,静态成员,虚拟继承,默认成员函数,作用域)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

🌏博客主页: 主页
🔖系列专栏: C++
❤️感谢大家点赞👍收藏⭐评论✍️
😍期待与大家一起进步!



一、继承的定义

它允许程序员在保持原有类特性的基础上进行扩展,增加功能,这样产生新的类,称派生类。

1.定义格式

【C++】继承的基本特性(定义,赋值转换,友元,静态成员,虚拟继承,默认成员函数,作用域),c++,开发语言,java
Person是父类,也称作基类。Student是子类,也称作派生类

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

【C++】继承的基本特性(定义,赋值转换,友元,静态成员,虚拟继承,默认成员函数,作用域),c++,开发语言,java
总结:

  1. 基类private成员在派生类中无论以什么方式继承都是不可见的。这里的不可见是指基类的私有成员还是被继承到了派生类对象中,但是语法上限制派生类对象不管在里面还是类外面都不能去访问它。
    【C++】继承的基本特性(定义,赋值转换,友元,静态成员,虚拟继承,默认成员函数,作用域),c++,开发语言,java

  2. 基类private成员在派生类中是不能被访问, 如果基类成员不想在类外直接被访问,但需要在派生类中能访问,就定义为protected。 可以看出保护成员限定符是因继承才出现的。

  3. 基类的私有成员在子类都是不可见, 基类的其他成员在子类的访问方式 == Min(成员在基类的访问限定符,继承方式),public > protected > private。

  4. 使用关键字class时默认的继承方式是private,使用struct时默认的继承方式是public,不过最好显示的写出继承方式。

  5. 在实际运用中一般使用都是public继承,几乎很少使用protetced/private继承,也不提倡使用protetced/private继承

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

1.派生类对象 可以赋值给 基类的对象 / 基类的指针 / 基类的引用。这里有个形象的说法叫切片或者切割。寓意把派生类中父类那部分切来赋值过去。
2.基类对象不能赋值给派生类对象。
【C++】继承的基本特性(定义,赋值转换,友元,静态成员,虚拟继承,默认成员函数,作用域),c++,开发语言,java
【C++】继承的基本特性(定义,赋值转换,友元,静态成员,虚拟继承,默认成员函数,作用域),c++,开发语言,java

三、继承的作用域

1. 在继承体系中基类和派生类都有独立的作用域。

2.子类和父类中有同名成员

子类和父类中有同名成员,子类成员将屏蔽父类对同名成员的直接访问,这种情况叫隐藏,也叫重定义。(在子类成员函数中,可以使用 基类::基类成员 显示访问)
【C++】继承的基本特性(定义,赋值转换,友元,静态成员,虚拟继承,默认成员函数,作用域),c++,开发语言,java

3.成员函数的隐藏

需要注意的是如果是成员函数的隐藏,只需要函数名相同就构成隐藏
【C++】继承的基本特性(定义,赋值转换,友元,静态成员,虚拟继承,默认成员函数,作用域),c++,开发语言,java

4.注意在实际中在继承体系里面最好不要定义同名的成员。

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

基类(父类):

class Person {
public:
	Person(const char*name)
		:_name(name)
	{
		cout << "Person()" << endl;
	}
	Person(const Person& p)
		:_name(p._name)
	{
		cout << "Person(const Person&p)" << endl;
	}
 
	Person& operator=(const Person& p) {
		cout << "Person operator=(const Person& p)" << endl;
		if (this != &p) {
			_name = p._name;
		}
		return *this;
	}

	~Person() {
		cout << "~Person()" << endl;
	}
protected:
	string _name;
};

派生类(子类)

class Student :public Person {
public:
	Student(const char*name="张三", int id = 0)
		//派生类的构造函数必须调用基类的构造函数初始化基类的那一部分成员。
		:Person(name)
		,_id(id)
	{}

	Student(const Student& s) 
		// 派生类的拷贝构造函数必须调用基类的拷贝构造完成基类的拷贝初始化。
		:Person(s)//切割
		,_id(s._id)
	{}

	Student& operator=(const Student& s) {
		//派生类的operator = 必须要调用基类的operator = 完成基类的复制
		if (this != &s) {
			Person::operator=(s);//发生切割
			_id = s._id;
		}
		return *this;
	}
		~Student()
	{
		// 析构函数的函数名被
		// 特殊处理了,统一处理成destructor

		// 显示调用父类析构,无法保证先子后父
		// 所以子类析构函数完成就,自动调用父类析构,这样就保证了先子后父
		 
		//析构函数:先析构子类后析构父类
		//构造函数:先构造父类后构造子类
	}

protected:
	int _id;
};

运行结果:
【C++】继承的基本特性(定义,赋值转换,友元,静态成员,虚拟继承,默认成员函数,作用域),c++,开发语言,java
总结:

  1. 派生类的构造函数必须调用基类的构造函数初始化基类的那一部分成员。如果基类没有默认的构造函数,则必须在派生类构造函数的初始化列表阶段显示调用。
  2. 派生类的拷贝构造函数必须调用基类的拷贝构造完成基类的拷贝初始化。
  3. 派生类的operator=必须要调用基类的operator=完成基类的复制。
  4. 派生类的析构函数会在被调用完成后自动调用基类的析构函数清理基类成员。因为这样才能
    保证派生类对象先清理派生类成员再清理基类成员的顺序。
  5. 派生类对象初始化先调用基类构造再调派生类构造。
  6. 派生类对象析构清理先调用派生类析构再调基类的析构。

【C++】继承的基本特性(定义,赋值转换,友元,静态成员,虚拟继承,默认成员函数,作用域),c++,开发语言,java

五、继承与友元

友元关系不能继承,也就是说基类友元不能访问子类私有和保护成员
【C++】继承的基本特性(定义,赋值转换,友元,静态成员,虚拟继承,默认成员函数,作用域),c++,开发语言,java
想要正常运行需要派生类也加上友元才可以

六、继承与静态成员

基类定义了static静态成员,则整个继承体系里面只有一个这样的成员。无论派生出多少个子类,都只有一个static成员实例 。

【C++】继承的基本特性(定义,赋值转换,友元,静态成员,虚拟继承,默认成员函数,作用域),c++,开发语言,java

七、菱形虚拟继承

1.菱形继承

【C++】继承的基本特性(定义,赋值转换,友元,静态成员,虚拟继承,默认成员函数,作用域),c++,开发语言,java
菱形继承的问题:从下面的对象成员模型构造,可以看出菱形继承有数据冗余和二义性的问题。在Assistant的对象中Person成员会有两份。
【C++】继承的基本特性(定义,赋值转换,友元,静态成员,虚拟继承,默认成员函数,作用域),c++,开发语言,java

2.虚拟继承

虚拟继承可以解决菱形继承的二义性和数据冗余的问题。如上面的继承关系,在Student和Teacher的继承Person时使用虚拟继承,即可解决问题。需要注意的是,虚拟继承不要在其他地方去使用。
【C++】继承的基本特性(定义,赋值转换,友元,静态成员,虚拟继承,默认成员函数,作用域),c++,开发语言,java

3.菱形虚拟继承原理:

class A
{
public:
 int _a;
};
// class B : public A
class B : virtual public A
{
public:
 int _b;
};
// class C : public A
class C : virtual public A
{
public:
 int _c;
};
class D : public B, public C
{
public:
 int _d;
};
int main()
{
 D d;
 d.B::_a = 1;
 d.C::_a = 2;
 d._b = 3;
 d._c = 4;
 d._d = 5;
 return 0;
}

1.菱形继承的内存分布

下图是菱形继承的内存对象成员模型:这里可以看到数据冗余
【C++】继承的基本特性(定义,赋值转换,友元,静态成员,虚拟继承,默认成员函数,作用域),c++,开发语言,java

2.虚拟继承内存分布

下图是菱形虚拟继承的内存对象成员模型:这里可以分析出D对象中将A放到的了对象组成的最下面,这个A同时属于B和C,那么B和C如何去找到公共的A呢?这里是通过了B和C的两个指针,指向的一张表。这两个指针叫虚基表指针,这两个表叫虚基表。虚基表中存的偏移量。通过偏移量可以找到下面的A。
【C++】继承的基本特性(定义,赋值转换,友元,静态成员,虚拟继承,默认成员函数,作用域),c++,开发语言,java
【C++】继承的基本特性(定义,赋值转换,友元,静态成员,虚拟继承,默认成员函数,作用域),c++,开发语言,java
【C++】继承的基本特性(定义,赋值转换,友元,静态成员,虚拟继承,默认成员函数,作用域),c++,开发语言,java文章来源地址https://www.toymoban.com/news/detail-624179.html

到了这里,关于【C++】继承的基本特性(定义,赋值转换,友元,静态成员,虚拟继承,默认成员函数,作用域)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • c++类和对象(拷贝构造、运算符重载、初始化列表、静态成员、友元等)

    拷贝构造函数的特征: 1、拷贝构造函数是构造函数的一个重载形式; 2、拷贝构造函数的参数只有一个且必须是同类类型对象的引用, 使用传值方式编译器直接报错 ,因为会引发无穷递归调用。 在c++中自定义类型 传值传参 的时候要调用拷贝构造函数。 3、若未显式定义,

    2024年02月15日
    浏览(36)
  • C++三大特性—继承“复杂的菱形继承及菱形虚拟继承”

    C++的一个大坑:菱形继承 希望这篇文章能让你理解什么是菱形继承,以及菱形继承的注意事项 单继承:一个子类只有一个直接父类时称这个继承关系为单继承 多继承:一个子类有两个或以上直接父类时称这个继承关系为多继承  java语言不支持多继承,只支持单继承。 菱形

    2024年02月03日
    浏览(42)
  • C++三大特性之一:继承

    C++三大特性:继承、多态和封装。继承是面向对象编程的一个核心概念,它允许我们根据一个已存在的类(基类或者叫父类),创建一个新的类(派生类或者叫子类),这个新的类继承了类的属性和行为。 1.继承格式。 class 子类名 :继承属性(publicprotectedprivate)父类名{

    2024年04月25日
    浏览(27)
  • C++ 面向对象三大特性——继承

    ✅1主页:我的代码爱吃辣 📃2知识讲解:C++ 继承 ☂️3开发环境:Visual Studio 2022 💬4前言:面向对象三大特性的,封装,继承,多态,今天我们研究研究 C++的继承 。 目录 一.继承的概念及定义 1.继承的概念  2.继承的定义 二. 继承关系和访问限定符  三.基类和派生类对象赋

    2024年02月12日
    浏览(66)
  • 【C++】三大特性 --- 继承的详细讲解

    目录 1.继承的概念及定义 1.1 继承的概念 1.2 继承定义 1.2.1定义格式 1.2.2继承关系和访问限定符 1.2.3继承基类成员访问方式的变化 2.基类和派生类对象赋值转换 3.继承中的作用域 4.派生类的默认成员函数 5.继承与友元 6.继承与静态成员 7.复杂的菱形继承及菱形虚拟继承 8.继承的

    2024年02月05日
    浏览(46)
  • 面向对象的三大特性之继承(C++)

    概念   继承机制是面向对象编编程使代码可以复用的最重要的手段,它允许程序员在保持原有类特性的基础上进行扩展,增加功能,这样产生新的类,称为派生类。继承呈现了面向对象程序设计的层次结构,体现了由简单到复杂的认知过程。继承是类设计层次的复用。 定

    2024年02月06日
    浏览(49)
  • C++ 类和对象(静态的static、友元、内部类、匿名对象、explicit)知识点+完整思维导图+实操图+深入细节通俗易懂建议收藏

            时间的步伐有三种:未来姗姗来迟,现在像箭一样飞逝,过往永远静立不动。本章是类和对象的一个收尾篇,相信通过这三篇类和对象的学习,应该你已经更加清楚了解了C++的类和对象。 话不多说安全带系好,发车啦 (建议电脑观看) 。 附:红色,部分为重点

    2024年02月06日
    浏览(47)
  • C++核心编程—类和对象,类的三大特性——封装、继承、多态

    纵有疾风起,人生不言弃。本文篇幅较长,如有错误请不吝赐教,感谢支持。 ①什么是对象? 生活中有各种各样的 事物 ,如人、动物、植物等在C++中将这些称为对象。 对象多种多样, 各种对象的属性也不相同 。 例如狗的品种,毛色,年龄等 各个对象都有自己的行为 ,例

    2024年02月07日
    浏览(62)
  • 【C++】万字一文全解【继承】及其特性__[剖析底层化繁为简](20)

    前言 大家好吖,欢迎来到 YY 滴C++系列 ,热烈欢迎! 本章主要内容面向接触过C++的老铁 主要内容含: 欢迎订阅 YY 滴C++专栏!更多干货持续更新!以下是传送门! YY的《C++》专栏 YY的《C++11》专栏 YY的《Linux》专栏 YY的《数据结构》专栏 YY的《C语言基础》专栏 YY的《初学者易

    2024年02月01日
    浏览(74)
  • [OpenCV][C++编程] cv::mat的定义与赋值

    可以通过在/目录下直接搜索opencv,确定opencv所在的目录: lopencv_core 是opencv的核心, -lopencv_highgui包含读取图像和显示图像的函数 -lopencv_imgproc包含图像处理函数(非机器学习方法),例如线性滤波,边缘检测、膨胀腐蚀、检测直线、仿射变换等等。 -lopencv_ml包含机器学习算法

    2024年02月09日
    浏览(43)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包