对C++中的继承分析和总结

2023-05-16

在这里插入图片描述

文章目录

  • 一、继承的概念
  • 二、继承的定义
    • 1. 继承的定义格式
    • 2. 继承方式和访问限定符
  • 三、基类和派生类的赋值规则
    • 1. 派生类赋值给基类
    • 2. 基类赋值给派生类
  • 四、继承中的重定义 (隐藏)
  • 五、派生类中的默认成员函数
    • 1. 不写派生类中的默认成员函数
    • 2. 写派生类中的默认成员函数
  • 六、继承中的友元函数
  • 七、继承中的静态成员
  • 八、菱形继承
    • 1. 菱形继承中的数据冗余和二义性
    • 2. 菱形虚拟继承
  • 九、继承和组合

一、继承的概念

继承机制是面向对象程序设计使代码可以复用的最重要的手段,它允许程序员在保持原有类特性的基础上进行扩展,增加功能,这样产生新的类,称派生类。继承呈现了面向对象程序设计的层次结构,体现了由简单到复杂的认知过程。以前我们接触的复用都是函数复用,而继承是类设计层次的复用所以继承的本质还是复用
举例如下:
在这里插入图片描述

二、继承的定义

1. 继承的定义格式

如下图所示,Person是父类,也称作基类。Teacher是子类,也称作派生类。
在这里插入图片描述

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

在这里插入图片描述
继承方式和访问限定符两两为一组,3*3一共有9种继承结果,如下图所示:

类成员 / 继承方式public继承protected继承private继承
基类的public成员派生类的public成员派生类的protected成员派生类的private成员
基类的protected成员派生类的protected成员派生类的protected成员派生类的private成员
基类的private成员在派生类中不可见在派生类中不可见在派生类中不可见

所以有两种方式去理解继承方式的语法:
一种为基类的私有成员,一种不是基类的私有成员。
1、基类private成员在派生类中无论以什么方式继承都是不可见的。这里的不可见是指基类的私有成员还是被继承到了派生类对象中,但是语法上限制派生类对象不管在类里面还是类外面都不能去访问它。
2、基类的私有成员在子类都是不可见。除了基类的基类的私有成员,基类其他成员在子类的访问方式为:Min(成员在基类的访问限定符,继承方式) 取它们两个的范围最小值。

注意:
1、保护和私有在父类中没有区别,区别体现在子类中,继承基类的private成员不可见,继承基类的protected是可见的。(可以看出保护成员限定符是因继承才出现的)。
2、使用关键字class时默认的继承方式是private,使用struct时默认的继承方式是public,不过最好显示的写出继承方式。

三、基类和派生类的赋值规则

1. 派生类赋值给基类

派生类对象 可以赋值给 基类的对象 / 基类的指针 / 基类的引用。这里有个形象的说法叫切片或者切割。意思是把派生类中父类那部分切来赋值过去。
代码举例如下:

class Person
{
protected:
	string _name;  // 姓名
	string _sex;  // 性别
	int _age;     // 年龄
};

class Student : public Person
{
public:
	int _id; // 学号
};


int main()
{
	Person p;
	Student s;

	// 父类=子类赋值兼容 ->> 切割  切片
	// 这里不存在类型转换,是语法天然支持行为
	p = s;
	Person* ptr = &s;
	Person& ref = s;  //没有加const,说明没有临时变量产生

	//存在类型转换,中间会产生临时变量,
	int i = 1;
	double d = 2.2;
	i = d;
	const int& ri = d; //要加const才能引用常量
}

注意: !!!!!!!!
不能把公有继承改成私有或者保护继承方式,否则实现不了切片;
因为存在访问权限的转换,比如基类中是公有访问限定符,用了保护继承方式,这样继承下来的访问权限就发生了改变,就不可以再赋值给基类了。
在这里插入图片描述

2. 基类赋值给派生类

基类对象不能赋值给派生类对象。
但是:
1、基类的指针可以通过强制类型转换赋值给派生类的指针。
2、基类的对象可以通过强制类型转换赋值给派生类的引用。

class Person
{
protected:
	string _name;  // 姓名
	string _sex;  // 性别
	int _age;     // 年龄
};

class Student : public Person
{
public:
	int _id; // 学号
};

int main()
{
	Person p;
	Student s;

	// 子类 = 父类
	// 很危险的,存在越界访问的风险
	Student* pptr = (Student*)&p;
	Student& ss = (Student&)p;
}

四、继承中的重定义 (隐藏)

我们都知道在继承体系中基类和派生类都有独立的作用域,那什么是作用域呢?
我们来看看这个例子,如果全局变量和局部变量的名字一样了,那要怎么调用呢?
我们有以下方法:变量名字前面加作用域
举例如下:

#include <iostream>
using namespace std;

int tmp = 0;
int main()
{
	int tmp = 233;
	cout << tmp << endl; //调用的是局部tmp
	cout << ::tmp << endl; //加作用域,调用的是全局变量tmp
	return 0;
}

我们再来看看我们的重定义概念:
定义: 子类和父类中有同名成员,子类成员将屏蔽父类对同名成员的直接访问,这种情况叫隐藏,也叫重定义。(在子类成员函数中,可以使用 基类::基类成员 显示访问)
注意: 如果是成员函数的隐藏,只需要函数名相同就构成隐藏

经典例题1:

class A
{
public:
	void fun()
	{
		cout << "func()" << endl;
	}
};

class B : public A
{
public:
	void fun(int i)
	{
		cout << "func(int i)->" << i << endl;
	}
};

//以下说法正确的是:
// 1:A和B的func构成函数重载
// 2:编译报错
// 3:运行报错
// 4:A和B的func构成函数隐藏

很明显,根据:如果是成员函数的隐藏,只需要函数名相同就构成隐藏,所以A和B的func函数构成隐藏。

经典例题2:

class A
{
public:
	void fun()
	{
		cout << "func()" << endl;
	}
};

class B : public A
{
public:
	void fun(int i)
	{
		cout << "func(int i)->" << i << endl;
	}
};

int main()
{
	B b;
	b.fun(1);
	b.fun();
}
//以下说法正确的是:
// 1:A和B的func构成函数重载
// 2:编译报错
// 3:运行报错
// 4:A和B的func构成函数隐藏

因为A和B的func构成函数隐藏,所以基类中的fun()函数被隐藏了,调用不了,从而编译报错。如果想要调用,要在前面加作用域,如:b.A::fun()。

五、派生类中的默认成员函数

学到现在,我们发现有6个默认成员函数,其中构造函数、析构函数、拷贝构造函数、赋值重载这四个默认成员函数是比较重要的,是我们下面重要研究的方面。

1. 不写派生类中的默认成员函数

所谓的“默认”就是我们不写,编译器会给我们自动生成一个。所以如果我们不写默认成员函数,编译器会默认生成的会干些什么事情呢?
1、如果我们不写默认生成的派生的构造和析构?
父类继承下来的 (调用父类默认构造和析构处理)
派生类的内置类型和自定义类型成员 (跟普通类一样)

2、 我们不写默认生成的拷贝构造和operator=?
父类继承下来得 (调用父类拷贝构造和operator=)
派生类的内置类型和自定义类型成员 (跟普通类一样)

2. 写派生类中的默认成员函数

那什么情况下必须自己写默认函数呢?我们总结出以下三点:
1、父类没有默认构造,需要我们自己显示写构造
2、如果子类有资源需要释放,就需要自己显示写析构
3、如果子类存在浅拷贝问题,就需要自己实现拷贝构造和赋值解决浅拷贝问题

自己写是自己写,那要我们怎么写呢?我们有以下两点:
1、对于父类成员调用父类的对应构造、拷贝构造、operator=和析构处理
2、自己成员按普通类处理。
举例如下:

//构建一个基类
class Person
{
public:
    //全缺省,没有参数,编译器自动生成的构造函数才是默认构造函数
	Person(const char* name)  //基类没有默认构造函数;		                        
		: _name(name)         
	{
		cout << "调用Person类构造函数" << endl;
	}

	Person(const Person& p)
		: _name(p._name)
	{
		cout << "调用Person类拷贝构造函数" << endl;
	}
	
	Person& operator=(const Person& p)
	{
		cout << "调用Person类赋值重载" << endl;
		if (this != &p)
			_name = p._name;
		return *this;
	}
	~Person()
	{
		cout << "调用Person类析构函数" << endl;
	}
protected:
	string _name; // 姓名
};

//构建子类,继承基类Person,下面演示怎么写默认成员函数
class Student : public Person
{
public:
	Student(const char* name,int id)
		:Person(name)   //调用父类的构造函数初始化_name
		,_id(id)
	{
		cout << "调用Student类的构造函数" << endl;
	}

	Student(const Student& tmp)
		:Person(tmp)   //这里把子类给父类,会发生切片;调用父类的拷贝构造
		,_id(tmp._id)
	{
		cout << "调用Student类的拷贝构造函数" << endl;
	}

	Student& operator=(const Student& tmp)
	{
		if (this != &tmp)
		{
			Person::operator=(tmp);  //调用父类的赋值重载
			_id = tmp._id;
		}
		cout << "调用Student类的赋值重载" << endl;
		return *this;
	}

	~Student()
	{
		cout << "调用Student类的析构函数" << endl;
	}
	//子类析构函数结束时,会自动调用父类的析构函数
protected:
	int _id;  //学号
};

int main()
{
	Person p("小明");
	Student s("张三",10086);

	Student s1(s);
	s1 = s;

	return 0;
}

注意:
子类析构函数结束时,会自动调用父类的析构函数,这样才能保证先析构子类成员,再析构父类成员;所以我们自己实现子类析构函数时,不需要显示调用父类析构函数。
如果我们想在子类析构函数中强制调用父类的析构函数,要注意什么呢?

~Student()
{
    //~Person()    
    //不能这样直接调用,析构函数名字会被统一处理成destructor()。为了符合多态条件
    //这样子类的析构函数跟父类的析构函数就构成隐藏,调用的是子类而不是父类
    
    //要加作用域调用才行
	Person::~Person();
}

总结: 从基类继承下来调用父类处理,自己的按普通类基本规则处理

六、继承中的友元函数

友元关系不能继承,也就是说基类友元不能访问子类私有和保护成员;
比如他是爸爸的朋友,但是不是我的朋友。

七、继承中的静态成员

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

class Person
{
public:
	static  int _count;
	Person()
	{
		_count++;
	}
};
int Person::_count = 0; //对静态成员进行初始化

class Student :public Person
{

};

class Teacher :public Person
{

};

int main()
{
	Person p;
	Student s;
	Teacher t;
	//调用静态成员可以有两种方式,
	//一种是对象. 调用;一种是类名:: 调用
	cout << Person::_count << endl;
	cout << Student::_count << endl;
	cout << Teacher::_count << endl;

	cout << p._count << endl;
	cout << s._count << endl;
	cout << t._count << endl;

	cout << &p._count << endl;
	cout << &s._count << endl;
	cout << &t._count << endl;
	return 0;
}

运行结果如下:
在这里插入图片描述

八、菱形继承

我们先来看看什么是单继承和多继承。
单继承:一个子类只有一个直接父类时称这个继承关系为单继承
在这里插入图片描述
多继承:一个子类有两个或以上直接父类时称这个继承关系为多继承
在这里插入图片描述
有了多继承之后,就有了菱形继承;
菱形继承:菱形继承是多继承的一种特殊情况。
在这里插入图片描述

1. 菱形继承中的数据冗余和二义性

菱形继承的问题:从下面的对象成员模型构造,可以看出菱形继承有数据冗余和二义性的问题。
举例如下:

//菱形继承
class A
{
public:
	int _aa;
};

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

class C : public A
{
public:
	int _cc;
};

class D :public B,public C
{
public:
	int _dd;
};

int main()
{
	D d1;
	// 这样会有二义性无法明确知道访问的是哪一个
	//d1._aa = 0;

	// 需要显示指定访问哪个父类的成员可以解决二义性问题,
	//但是数据冗余问题无法解决
	d1.B::_aa = 0;
	d1.C::_aa = 2;
	return 0;
}

菱形继承的内存图:
在这里插入图片描述

2. 菱形虚拟继承

所以为了解决菱形继承的二义性和数据冗余,菱形虚拟继承就出来了;
虚拟继承可以解决菱形继承的二义性和数据冗余的问题。
如上面的继承关系,在B和C的继承A时使用虚拟继承,即可解决问题。需要注意是,虚拟继承不要在其他地方去使用。
举例如下:

//菱形虚拟继承
class A
{
public:
	int _aa;
};

class B :virtual public A
{
public:
	int _bb;
};

class C : virtual public A
{
public:
	int _cc;
};

class D :public B,public C
{
public:
	int _dd;
};

int main()
{
	D d1;
	d1.B::_aa = 1;
	d1._bb = 2;

	d1.C::_aa = 3;
	d1._cc = 4;

	d1._dd = 5;
	return 0;
}

可是虚拟继承是怎么解决数据冗余和二义性的问题的呢?我们还是先来看看菱形虚拟继承的内存图:
在这里插入图片描述
在这里插入图片描述

可是为什么D中B和C部分要去找属于自己的A呢?当然是有理由的,看看下面这一种情况就知道了:

D d;
B b = d;
C c = d;
//当子类对象赋值给父类对象时,要发生切片,
//所以d要去找出B/C成员中的A才能赋值过去

B* pb=&d;
pb->_aa=5;
pb->_bb=6;
//同样的道理,子类的地址给父类的指针时,
//父类的指针要找到子类成员的地址才行

九、继承和组合

public继承是一种是什么的关系。也就是说每个派生类对象都是一个基类对象。
(如Person 和 Student)
组合是一种有什么的关系。假设B组合了A,每个B对象中都有一个A对象。
(如轮胎和汽车 、眼睛和头)
代码举例如下:

class A
{
public :
	int _aa;
};
//继承
class B :public A
{
public:
	int _bb;
};

class C
{
public:
	int _cc;
};
//组合
class D
{
public:
	C _target;
	int _dd;
};

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

对象组合是类继承之外的另一种复用选择。新的更复杂的功能可以通过组装或组合对象来获得。对象组合要求被组合的对象具有良好定义的接口。这种复用风格被称为黑箱复用;
因为对象的内部细节是不可见的。对象只以“黑箱”的形式出现。 组合类之间没有很强的依赖关系,耦合度低。优先使用对象组合有助于你保持每个类被封装。

那我们是使用继承好还是组合好呢?
答案是完成符合哪一个就用哪一种方式,都符合就优先组合。
举一个例子:
比如A类合C类都有3个共有成员合3个保护成员;
但是B类公有继承A类,B就可以直接访问A类的公有成员合保护成员;
而D类和C类是组合,D只能访问C类的公有成员。
所以组合类之间没有很强的依赖关系,耦合度低。优先使用对象组合有助于你保持每个类被封装。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

对C++中的继承分析和总结 的相关文章

  • MAC安装JD-GUI反编译工具

    JD GUI 是一款反编译工具 本文介绍的是 JD GUI的安装方式 xff0c very easy 首先打开官网 xff1a http java decompiler github io 无法访问的朋友可以私信我要jar包 当然你也可以去
  • 转载:配置darknet_ros实现yolo检测

    来自第三届华南农业大学人工智能协会 xff1a 会长部 麦彦恒出品 配置darknet ros实现yolo检测 M朗拿度的博客 CSDN博客
  • AUTOSAR(一)基本概述

    提示 xff1a 文章写完后 xff0c 目录可以自动生成 xff0c 如何生成可参考右边的帮助文档 文章目录 目录 文章目录 一 什么是AUTOSAR xff1f 二 为什么要使用AUTOSAR xff1f 三 AUTOSAR版本 一 什
  • 台达PLC与单片机的通讯

    最近由于工作需要用PLC与单片机通讯 xff0c 以此用PLC来控制单片机 xff0c 使单片机作为一个IO扩展模块来使用 这是第一次尝试自己写代码来使两个器件通讯 xff0c 故在此做一下笔记 xff0c 顺便巩固一下在这个过程中所学到的
  • VirtualBox 创建了备份(系统快照),如何恢复备份

    打开软件 xff0c 就进入了以下界面 这里并没有什么备份操作 xff0c 然后我们点开这个位置 点击备份就会到达这个页面 点击自己想要恢复的备份就可以了 xff0c 不过得先要关机
  • 详细讲解算术/范围编码(AC)

    算术编码 xff08 Arithmetic coding xff09 是一种无损数据压缩技术 xff0c 它能够将任意离散的符号串 xff08 如字母 像素值等 xff09 压缩为一个实数区间 xff0c 并可以通过解码还原出原始数据 范围
  • 50家大厂面试万字精华总结,数据库事务深入分析,最全指南

    什么是自旋锁和互斥锁 xff1f 由于CLH锁是一种自旋锁 xff0c 那么我们先来看看自旋锁是什么 xff1f 自旋锁说白了也是一种互斥锁 xff0c 只不过没有抢到锁的线程会一直自旋等待锁的释放 xff0c 处于busy waiting
  • MySQL万字精华总结!你连基础的JVM运行时内存布局都忘了?含面试题+答案

    前言 Netty 是一款基于 Java 的网络编程框架 xff0c 能为应用程序管理复杂的网络编程 多线程处理以及并发 Netty 隐藏了样板和底层代码 xff0c 让业务逻辑保持分离 xff0c 更加易于复用 使用 Netty 可以得到一
  • 【STM32】 AMS1117(稳压)模块

    目录 一 xff1a 介绍 二 xff1a 应用 三 xff1a AMS1117 3 3芯片实物图 四 xff1a 特性 五 xff1a 典型应用 六 xff1a 引脚分配 七 xff1a 可调 固定低压差线性稳压器结构 一 xff1a 介
  • 【网络】连接服务器失败(错误原因:Connection refused)| error 111: (111) Connection refused 原因分析

    服务器拒绝原因 xff1a connect 发起TCP连接请求被拒绝是由于目标服务器上无对应的监听套接字 xff08 IP amp amp PORT xff09 xff08 没有监听 无法创建 监听别的IP 端口 xff09 有几个可能性
  • 【C++软件开发】Linux相关面试题型

    一 xff1a Linux的I O模型介绍以及同步异步阻塞非阻塞的区别 xff08 超级重要 xff09 xff08 IO过程包括两个阶段 xff1a xff08 1 xff09 内核从IO设备读写数据和 xff08 2 xff09 进程从
  • 【C++】 STL详解

    目录 一 xff1a 泛型编程 二 xff1a 什么是STL 三 xff1a STL发展 四 xff1a STL组件 五 xff1a 容器 六 xff1a 类型成员 七 xff1a 适配器 八 xff1a 迭代器 九 xff1a 算法 十
  • 12.STM32freeRTOS---递归互斥信号量

    文章目录 前言一 创建递归互斥信号量二 释放递归互斥信号量三 获取递归互斥信号量四 官方例程总结 前言 递归互斥信号量可以看成是一个特殊的互斥信号量 对于互斥信号量 xff0c 获取了互斥信号量的任务就不能再次获取这个互斥信号量 xff0c
  • toString用法

    toString是定义在java lang Object的方法 xff0c 因此所有类都可以使用toString方法 xff0c 但是 toString方法本身返回的是地址信息而对于String Date File 包装类 等都重写了toS
  • 商医通项目总结

    一 项目概述 简介 尚医通即为网上预约挂号系统 xff0c 网上预约挂号是近年开展的一项便民就医服务 xff0c 旨在缓解看病难 挂号难的就医难题 网上预约挂号全面提供的预约挂号业务从根本上解决了这一就医难题 随时随地轻松挂号 xff0c
  • docker安装以及遇到的问题

    目录 一 docker安装 二 安装中可能碰到的问题 1 WSL 2 installation is incomplete 一 docker安装 docker官网下载 xff1a Docker Desktop Docker xff0c 下载
  • STM32MP157实验(三)——按键扫描和中断

    文章目录 按键扫描设计需求基础知识硬件设计STM32CubeIDE设计MX设置代码设计 实验结果 按键中断设计需求基础知识硬件设计STM32CubeIDE设计MX设置代码设计 总结 按键扫描 设计需求 通过按键扫描的方式实现 xff0c 按
  • 一篇博客实现嵌入式入门

    文章目录 前言最小系统和C语言最小系统原理图电源电路时钟电路复位电路调试 下载电路 嵌入式C语言基础知识数据类型const用法修饰变量修饰数组修饰指针修饰函数参数 作用域与static用法extern的用法volatile的用法struct
  • 驱动开发(一)——(单片机程序、Linux应用程序与驱动程序分析)

    文章目录 前言157准备工作配置交叉编译链编译内核编译解压glibc 单片机程序应用程序驱动程序三者的关系 前言 学习资料 xff0c 跟的韦东山老师的视频 xff0c 大家可以上百问网下载资料 百问网 我使用的开发板是STM32MP157

随机推荐

  • 驱动开发(五)——驱动设计思想(面向对象/分层/分离)

    文章目录 设计思想面向对象分层分离 实验手册资源驱动程序 led drv cled operations h芯片相关chip gpio cled resource h单板相关 board MP157 led c应用测试程序Makefile
  • 【shell】遇到错误退出set -e|set -u|set -x|shell 退出时执行|捕捉信号trap

    目录 遇到错误退出 简介和使用 set e 的陷阱 1 xff0c 管道命令 2 xff0c grep匹配不到会导致退出 shell退出时执行 接收信号 trap 用途 trap介绍 列出所有信号的数值和名字 trap的注意事项 遇到错误退
  • 我的世界java版官方网站,讲的太透彻了

    简介 基于SpringCloud Hoxton SR1 43 SpringBoot 2 2 4 RELEASE 的 SaaS型微服务脚手架 xff0c 具备用户管理 资源权限管理 网关统一鉴权 Xss防跨站攻击 自动代码生成 多存储系统 分
  • 深入理解java虚拟机pdf,GitHub已标星16k

    专题5 xff1a Java序列化 1 什么是java序列化 xff0c 如何实现java序列化 xff1f 2 保存 持久化 对象及其状态到内存或者磁盘 3 序列化对象以字节数组保持 静态成员不保存 4 序列化用户远程对象传输 5 Ser
  • 成功入职阿里月薪45K,附赠课程+题库

    网站基础知识 xff08 网站架构及其演变过程 43 常见协议和标准 43 DNS的设置 43 Java中Socket的用法 43 HTTP协议 43 详解Servlet 43 Tomcat分析 xff09 俯视 Spring MVC xf
  • 快醒醒吧!springcloud分布式事务面试题

    一 什么是架构和架构本质 在软件行业 xff0c 对于什么是架构 xff0c 都有很多的争论 xff0c 每个人都有自己的理解 此君说的架构和彼君理解的架构未必是一回事 因此我们在讨论架构之前 xff0c 我们先讨论架构的概念定义 xff0
  • 基于java实现直播,太牛了!

    美团技术一面20分钟 晚7点 xff0c 因为想到下周一才面试 xff0c 我刚准备出去打个羽毛球 xff0c 北京的电话就来了 面试官各种抱歉 xff0c 说开会拖延了 1 自我介绍 说了很多遍了 xff0c 很流畅捡重点介绍完 2 问我
  • java银行面试题目及答案,顺利拿到offer

    二 常见的并发问题 1 脏读 一个事务读取了另一个事务未提交的数据 2 不可重复读 一个事务对同一数据的读取结果前后不一致 两次读取中间被其他事务修改了 3 幻读 幻读是指事务读取某个范围的数据时 xff0c 因为其他事务的操作导致前后两次
  • 白嫖党最爱!javasocket服务端向客户端发消息

    一 公务员都不要35岁以上的 xff0c 何况大公司 这让很多人感到惶恐 xff0c 现在职场上有一种现象 xff1a 很多用人单位会在招聘信息上明确标注 xff0c 年龄需在35岁以下 为什么有经验 有人脉的职场中年人会如此遭 嫌弃 呢
  • Mybatis源码解析:21道Java基础面试题及答案

    10 HashMap和HashTable的区别 答案 xff1a Hashtable和HashMap类有三个重要的不同之处 1 第一个不同主要是历史原因 Hashtable是基于陈旧的Dictionary类的 xff0c HashMap是J
  • Mybatis源码解析:Java泛型详解

    注意 xff1a 泛型的类型参数只能是类类型 xff0c 不能是基本属性类型 xff1b 不能对确切的泛型类型使用instanceof操作 如下面的操作是非法的 xff0c 编译时会出错 if ex num instanceof Gener
  • MySQL数据库优化:Java程序员秋招三面蚂蚁金服

    自我介绍 JVM如何加载一个类的过程 xff0c 双亲委派模型中有哪些方法 xff1f HashMap如何实现的 xff1f HashMap和Concurrent HashMap区别 xff0c Concurrent HashMap 线程安
  • 【shell】shell脚本模板

    参考 xff1a cShell脚本模板 运维 64 小兵的博客 CSDN博客 bin bash set e 打开异常退出功能 set x 打开Debug功能 定义变量 source etc profile 避免用contab ansible
  • ROS中自定义头文件、源文件和可执行文件调用

    编写头文件 头文件创建在功能包 include 功能包名路径下 xff0c 示例内容如下 xff1a ifndef haha define haha namespace haha ns class Person public void ru
  • STM32/51单片机进阶技一 裸机编程(多任务处理编程思想与代码风格)

    文章目录 系列文章目录前言一 裸机编程是什么 xff1f 二 使用步骤 1 main c主函数处理2 中断函数处理总结 前言 在单片机编程当中 xff0c 我们难免会用单片机处理1个 xff0c 2个简单的任务 xff0c 但是当任务数量超
  • 用JavaScript写的猜数字游戏

    先输出游戏目的 xff0c 用Math Random找到随机数 xff0c 其取值在0 1之间 xff0c 故乘100 直到输入的数字和随机数a相等时才跳出循环 否则 xff0c 判断输入值如果大于随机数 xff0c 则输出你猜的数偏大哦
  • 使用JS脚本打开多个网页的方法

    01 问题 如每天都需要刷新重复的网页或许数据 有什么解决办法吗 02 解决方案 大家可以移步是你的Sakura的 打开多个相关联的网页 js脚本打开网页方法 03 代码 span class token tag span class to
  • 安装 rotors-gazebo 时 melodic版本遇到的问题

    针对找不到qt gui的问题 Could not find a package configuration file provided by 34 qt gui 34 with any of the following names qt g
  • Promethus(普罗米修斯)安装与配置

    1 普罗米修斯概述 Prometheus 是由go语言 golang 开发 是一套开源的监控 amp 报警 amp 时间序列数 据库的组合 适合监控docker容器 Prometheus是最初在SoundCloud上构建的开源系统监视和警报
  • 对C++中的继承分析和总结

    文章目录 一 继承的概念二 继承的定义1 继承的定义格式2 继承方式和访问限定符 三 基类和派生类的赋值规则1 派生类赋值给基类2 基类赋值给派生类 四 继承中的重定义 隐藏 五 派生类中的默认成员函数1 不写派生类中的默认成员函数2 写派