learn C++ NO.1——命名空间域、输入输出、函数重载

news2024/11/18 1:43:29

前言

什么是C++

C++(c plus plus)是一种计算机高级程序设计语言,由C语言扩展升级而产生,最早于1979年由本贾尼·斯特劳斯特卢普在AT&T贝尔工作室研发。C语言是结构化和模块化的语言,适合处理较小规模的程序。对于复杂的问题,规模较大的程序,需要高度的抽象和建模时,C语言则不合适。为了解决软件危机, 20世纪80年代, 计算机界提出了OOP(object
oriented programming:面向对象)思想,支持面向对象的程序设计语言应运而生。Bjarne Stroustrup博士在C语言的基础上引入并扩充了面向对象的概念,发明了一种新的程序语言。为了表达该语言与C语言的渊源关系,命名为C++。因此:

C++是基于C语言而产生的,它既可以进行C语言的过程化程序设计,又可以进行以抽象数据类型为特点的基于对象的程序设计,还可以进行面向对象的程序设计。

1.namespace关键字

当使用C语言进行开发时,不同程序员写的不同模块间,难免存在一些列的命名冲突。而在C++中,引入了一个新的关键字即namespace(命名空间)。命名空间可以有效地避免命名冲突和名字污染。

1.1什么是命名冲突

#include<stdio.h>

int rand = 10;

int main()
{
	printf("%d\n", rand);
	return 0;
}

在这里插入图片描述

运行上面的代码,可以发现控制台窗口输出了10。

#include<stdio.h>
#include<stdlib.h>

int rand = 10;

int main()
{
	printf("%d\n",\n);
	return 0;
}

在这里插入图片描述
因为全局变量rand和<stdlib.h>中的函数rand产生了命名冲突。那么应该怎么解决这个问题呢?这时候就可以使用命名空间来进行域隔离。

1.2 命名空间域

1.2.1 域的概念

域这个概念其实C语言里就有,那就是全局域与局部域。相同的域内,不能有两个相同名字的标识符。当全局域和局部域命名冲突时,局部域优先。而命名空间域,也就是用namespace关键字创建的域。

1.2.2 域作用限定符

当全局域和局部域有命名冲突时,编译器默认是从局部域例访问相同名字的变量。如果此时想访问全局域的变量,就需要使用域作用限定符(::)。当域作用限定符的左操作数为空时,表示从全局域中访问,当域操作限定符的左操作数为命名空间名,则表示从命名空间域中访问。

#include<stdio.h>

int a = 0;

int main()
{
	int a = 1;
	
	printf("%d\n",a);
	// ::即域作用限定符
	printf("%d\n",::a);
	return 0;
}

1.2.3 命名空间域展开

当全局域和局部域以及命名空间域变量名冲突时,编译器默认先访问局部域。当全局域和命名空间域变量命名冲突时,编译器默认访问全局域。若此时局部域和全局域不存在,编译器就不会去访问命名空间域。

在这里插入图片描述
如果想访问命名空间域里的变量,可以有三种方法进行访问。第一种是直接展开命名空间域,第二种是指定命名空间域,第三种是展开命名空间域的一部分。

#include<stdio.h>

//int a = 0;

namespace sinzz
{
	int a = 2;
}

//展开命名空间域
using namespace sinzz;

int main()
{
	//int a = 1;
	
	//指定访问命名空间域
	printf("%d\n",sinzz::a);
	return 0;
}

补充:当展开了命名空间域后,依旧可以使用指定访问该命名空间域。

//展开一部分举例

namespace sinzz
{
	int a = 20;
	int b = 30;
	int c = 2;
}

//展开命名空间域的一部分
using sinzz::a;

int main()
{
	printf("%d\n",a);
	printf("%d\n",sinzz::b);
	printf("%d\n",sinzz::c);
	return 0;
}

在这里插入图片描述

补充:在平时练习时,可以直接展开命名空间域。如果是项目的开发,直接展开命名空间域可能会导致和C++库里产生冲突,此时就可以指定访问命名空间域或者展开部分不会冲突的命名空间来避免冲突。

1.3 命名空间域的嵌套

当一个命名空间域设计的足够大时,在这个命名空间域内部,难免存在一系列的命名冲突。命名空间域的嵌套就可以很好的解决这个问题。
在这里插入图片描述

namespace sinzzA
{
	int a = 2;
	int Add(int x, int y)
	{
		return x + y;
	}

	namespace sinzzB
	{
		int a = 6;
		int Mul(int x, int y)
		{
			return x * y;
		}
	}
}

//对嵌套的命名空间进行访问
int main()
{	
	printf("%d\n",sinzzA::a);
	printf("%d\n", sinzzA::sinzzB::a);
	printf("%d\n",sinzzA::sinzzB::Mul(3,3));
	return 0;
}

在这里插入图片描述

1.4 命名空间域的合并

一个工程中可以有许多相同的命名空间,它们最后会在编译后合并成一个命名空间。
在这里插入图片描述
通过上图可以发现,虽然sinzz这个命名空间被定义在了三个不同的文件中,但是最后这三个命名空间还是会合并成一个命名空间的。

2.C++的输入和输出

注意事项:

  1. 使用cout标准输出对象(控制台)和cin标准输入对象(键盘)时,必须包含< iostream >头文件以及按命名空间使用方法使用std。
  2. cout和cin是全局的流对象,endl是特殊的C++符号,表示换行输出,他们都包含在包含< iostream >头文件中。
  3. << 是流插入操作符,>>是流提取操作符。
  4. 使用C++的方式输入和输出更为方便,因为不需要像scanf,printf那样手动控制格式。而是可以自动识别格式进行输入和输出。

2.1 C++的输出

首先,包含iostream头文件,然后,展开std命名空间,使用<<流插入操作符,将想输出的内容插入到cout函数中,然后就可以完成控制台窗口的输出。


#include<iostream>

using namespace std;

int main()
{
	//endl--换行符
	cout << "hello world" << endl;
	return 0;
}

在这里插入图片描述
cout这个输出函数相比较于printf函数,还是很智能的。cout可以自动匹配类型进行输出。

int main()
{
	int a = 10;
	double b = 2.345;

	cout << a << " " << b << endl;
	
	return 0;
}

在这里插入图片描述

2.2 C++的输入

首先,包含iostream头文件,然后,展开std命名空间,使用>>流提取操作符,将想输入的内容提取到cin函数中,然后就可以完成输入。

int main()
{
	int a = 10;
	double b = 2.3;

	cout << a << " " << b << endl;

	cin >> a >> b;
	cout << a << " " << b << endl;

	return 0;
}

在这里插入图片描述
通过上图可以发现,cout函数在输出时会丢失精度。要想解决这个问题的方法有两个,第一个是使用C++的方式来修正,第二个就是使用printf函数来制定格式输出。我个人还是喜欢用第二个方式来解决这一问题。由于C++是兼容C语言的,所以在C++代码中可以混用C语言。

2.3头文件的区别

早期C语言的标准库将其功能实现在全局域中,所以会以.h的格式做出区别。而后来在C++标准库中将功能实现在了std命名域中,为了和C头文件做出区分,也为了正确使用命名空间。后来就规定了C++库不在结尾处以.h格式标识。当然在一些早期的编译器(如vc++6.0)中,是可以使用<iostream.h>这样的方式包含头文件的。但是,后续的编译器均不支持该方式,所以我们需要以< iostream >+命名空间的方式使用C++的输入输出。

3.缺省参数

3.1 缺省参数的概念

缺省参数就是在函数的声明或者定义(定义是一种特殊的声明)时,给定一个缺省值。若调用该函数没有指定实参进行传参,那么参数部分就为给定的缺省值。

#include<iostream>

using namespace std;

void Test(int a = 10)
{
	cout << a <<endl;
}

int main()
{
	Test();//未指定参数,调用函数使用缺省参数
	Test(100);//传参指定参数,不使用缺省参数
	return 0;
}

在这里插入图片描述

3.2缺省参数的分类

3.2.1 全缺省参数

#include<iostream>

using namespace std;

void test(int a = 10, int b = 20, int c = 30)
{
	cout << "a= " << a << endl;
	cout << "b= " << b << endl;
	cout << "c= " << c << endl;
}

int main()
{
	test();
	return 0;
}

在这里插入图片描述

3.2.2 半缺省参数

#include<iostream>

using namespace std;

void test(int a , int b = 20, int c = 30)
{
	cout << "a= " << a << endl;
	cout << "b= " << b << endl;
	cout << "c= " << c << endl;
}

int main()
{
	test(1);
	test(1, 2, 3);
	return 0;
}

在这里插入图片描述

3.3缺省参数使用注意事项

1、缺省参数的定义必须从左向右依次定义,中间不能有间隔。
在这里插入图片描述
2、缺省参数不能同时出现在定义和声明当中。如果声明与定义位置同时出现,恰巧两个位置提供的值不同,那编译器就无法确定到底该用那
个缺省值。在这里插入图片描述
通常在写缺省参数时,都把缺省参数放在函数的声明当中。当然在VS2019编译器下,即使声明和定义的缺省值相同,也还是会报错的。

3、缺省参数的值必须是常量或全局变量。
在这里插入图片描述

4.函数重载

4.1 函数重载的概念

函数重载指的是一个函数名可以被多个参数类型不同参数顺序不同或者参数个数不同的函数共用。C++标准规定在同一作用域下函数重载才是合法的。函数重载通常用于处理实现功能类似但是数据类型不同的函数上。函数重载可以有效地解决工程中的命名污染问题。

#include<iostream>

using namespace std;


int Add(int x, int y)
{
	return x + y;
	return 0;
}

double Add(double x, double y)
{
	return x + y;
}

int main()
{
	cout << Add(1, 2) << endl;
	cout << Add(2.3, 3.2) << endl;
	return 0;
}

在这里插入图片描述

4.2 函数重载的原理

为什么C语言不支持函数重载,而C++支持函数重载呢?C++是如何支持函数重载的呢?带着这两个问题,开始该部分的讲解
首先我们需要明白C/C++程序从代码到程序的过程

4.2.1命名修饰

因为在C语言编译器中,链接过程中,编译器通过函数名在其他的.o文件中查找该函数的地址,而如果函数重名,就不能准确找出那个需要的函数,造成歧义,而在C++编译器中,编译器会对函数名进行名字修饰,即在函数名中加入参数信息,这样在链接过程中,查找函数地址不会造成歧义。在这里插入图片描述

4.2.1.1 linux环境下的观察

vs编译器对命名修饰过于复杂,不方便观察。所以这里用linux环境下的gcc和g++编译器来进行观察。

在这里插入图片描述
通过对于gcc编译后产生后目标文件观察可以发现,C语言其实是没有函数进行命名修饰的。下面就将代码采用g++编译。
在这里插入图片描述
通过上图便可以清晰地看见了命名修饰就是支持函数重载的基本原理。g++编译器的命名修饰规则为_Z+函数名长度+函数名+参数类型。当然,上图也可以证明只有返回值不同,参数类型,参数数量和参数顺序都相同。这样是不构成函数重载的。因为在调用函数时无法确定它的具体类型。

4.2.1.2 windows环境下的观察

在这里插入图片描述
从上图也可以看到,编译器是在链接的时候再回去找func函数的定义,所以这里报的是链接错误,而命名修饰是编译器在编译阶段就处理。
在这里插入图片描述
在这里插入图片描述

4.3 extern “C”

由于在一个大型的C++项目中,需要多人开发。而一些人擅长C++,当然也有一些人会使用C语言。由于C和C++编译器对函数名字修饰规则的不同,可能就会导致链接失败。。那么就要在函数前加上extern “C”。

//举例使用 extern "C"

#ifdef __cplusplus
extern "C"
{
#endif
	int Add(int left, int right);
	int Sub(int left, int right);
#ifdef __cplusplus
}
#endif

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/451772.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Cache存储系统详解(全相联映射、直接映射、组相联映射、替换策略和性能计算)

1. 存储系统的层次结构 为了解决容量、速度和价格之间的矛盾&#xff0c;把各种不同存储容量&#xff0c;不同存取速度&#xff0c;不同价格的存储器&#xff0c;按照一定的体系结构组织起来&#xff0c;使所存放的程序和数据按层次分布在各存储器中&#xff0c;形成---多层次的…

读书笔记//《数据科学工程实践》

出版时间&#xff1a;2021年11月 副标题&#xff1a;用户行为分析、A/B实验、SQLFlow 作者们是一线互联网企业的数据科学家、数据分析师和算法工程师&#xff0c;主要就职于滴滴、部分就职于腾讯、快手等。 点评&#xff1a;神仙下凡布道。感谢大佬们的分享。本书让我领略了大厂…

小白也能看懂,解读数据中台

不同的企业对数据有不同的需求。企业数据应用不断更新迭代&#xff0c;企业的中台系统也需要不断变化。从数据处理与数据治理两个维度出发&#xff0c;可以设计一个解耦的数据中台体系架构。该数据中台体系架构具有一定的柔性&#xff0c;可按照企业应用需求进行组合&#xff0…

多语言(CurlPHPPHPsdkJAVAC#Python)调用阿里巴巴商品API接口

2月2日消息&#xff0c;《晚点LatePost》独家报道&#xff0c;阿里集团国内批发业务1688近期完成了一系列组织和业务调整。其中&#xff0c;原1688商贸发展中心和产地发展中心合并为1688商家发展中心&#xff0c;由原商贸发展中心总经理王强负责&#xff1b;1688新成立分销供应…

苹果天气应用专利获批,苹果Find My技术改变防丢技术走向

根据美国商标和专利局&#xff08;USPTO&#xff09;公示的清单&#xff0c;苹果近日获得了名为“用于管理天气信息的用户界面”专利&#xff0c;编号为 US 11630559 B2。 苹果在专利描述中表示&#xff0c;部分管理天气信息的技术复杂且效率低下&#xff0c;用户需要多次点击…

spring redis Sentinel 哨兵 原理

客户端选择 redis 常用的连接客户端 有三个 Jedis&#xff1a;是老牌的Redis的Java实现客户端&#xff0c;提供了比较全面的Redis命令的支持&#xff0c;Redisson&#xff1a;实现了分布式和可扩展的Java数据结构。Lettuce&#xff1a;高级Redis客户端&#xff0c;用于线程安…

el-table合计功能滚动条层级问题

问题描述 版本&#xff1a;2.15.13 el-table在使用合计功能及固定列功能的同时&#xff0c;由于固定列的结构是固定区域增加了div加上定位&#xff0c;用来盖住下面的内容。当使用了合计功能的时候滚动条的区域在el-table__body-wrapper会导致固定列区域下的滚动条被挡住&…

计算机网络三:运输层

一、运输层 1. 概述 运输层协议为运行在不同主机上的应用进程之间提供了逻辑通信功能&#xff0c;使得不同主机好像直接连在一起一样 运输层协议是在端系统中而不是在路由器中实现的。网络路由器仅作用于网络层分组(即数据报)的网络层字段&#xff0c;而不检查封装在该数据报…

微搭低代码学习之数据展示

低代码平台是一个快速发展的领域&#xff0c;未来有着广阔的发展前景。以下是一些低代码平台未来的发展方向&#xff1a; 1.人工智能和机器学习 随着人工智能和机器学习技术的不断发展&#xff0c;低代码平台将能够更好地利用这些技术来提高应用程序的智能化和自动化水平。例如…

APP渗透—绕过反代理、反证书检测

APP渗透—绕过反代理、反证书检测 1. 前言1.1. 无法获取数据包情况 2. 反代理2.1. 反代理情况2.1.1. 某牛牛反代理2.1.2. 某探反代理 2.2. 绕过反代理2.2.1. Proxifier设置2.2.1.1. 设置代理服务器2.2.1.2. 配置代理规则2.2.1.3. 检测状态 2.2.2. 抓包测试 2.3. 总结 3. 反证书…

用HTML+CSS简单的画一个支付宝页面(超详细)

&#x1f648;作者简介&#xff1a;练习时长两年半的Java up主 &#x1f649;个人主页&#xff1a;老茶icon &#x1f64a; ps:点赞&#x1f44d;是免费的&#xff0c;却可以让写博客的作者开兴好久好久&#x1f60e; &#x1f4da;系列专栏&#xff1a;Java全栈&#xff0c;计…

Pyqt实现合并PDF遇到的问题集合

1.exit code -1073740791报错 pycharm遇到如下报错&#xff1a; “Process finished with exit code -1073740791 (0xC0000409)” 就是遇到这种问题就不知道问题在哪里&#xff0c;有点摸不着头脑 解决措施&#xff1a; 1.点击导航栏“Run”后选择“Edit Configurations” …

Python机器学习、深度学习技术提升气象、海洋、水文领域实践应用

Python是功能强大、免费、开源&#xff0c;实现面向对象的编程语言&#xff0c;在数据处理、科学计算、数学建模、数据挖掘和数据可视化方面具备优异的性能&#xff0c;这些优势使得Python在气象、海洋、地理、气候、水文和生态等地学领域的科研和工程项目中得到广泛应用。可以…

Keil使用 fromelf 生成bin文件

一、语法格式如下&#xff1a; fromelf [options] input_file [options] 选项如下&#xff0c;可以组合使用&#xff0c;两者之间用空格隔开&#xff1a; 二、在Keil中的使用过程 1、配置Output&#xff0c;生成可执行文件 aa即为可执行文件名&#xff0c;后缀为axf。…

十三、51单片机之EEPROM(I2C)

1、EEPROM简介 (1)存储设备类型&#xff1a;ROM、RAM、PROM(可编程ROM)、EPROM(可擦除ROM)、EEPROM(电可擦除ROM)。 (2)为什么需要EEPROM&#xff1f; 某些数据内容我们需要掉电不丢失且在程序运行中可以修改这些数据内容&#xff0c;这就需要用到EEPROM。 (3)EEPROM和flas…

家庭智能开关通断—Homekit智能

智能通断器&#xff0c;也叫开关模块&#xff0c;可以非常方便地接入家中原有开关、插座、灯具、电器的线路中&#xff0c;通过手机App或者语音即可控制电路通断&#xff0c;轻松实现原有家居设备的智能化改造。 随着智能家居概念的普及&#xff0c;越来越多的人想将自己的家改…

Rust之泛型、特性和生命期(一):基本概念

开发环境 Windows 10Rust 1.69.0 VS Code 1.77.3 项目工程 这里继续沿用上次工程rust-demo 泛型、特性和生命期 每种编程语言都有有效处理概念重复的工具。在Rust中&#xff0c;一个这样的工具就是泛型&#xff1a;具体类型或其他属性的抽象替身。我们可以表达泛型的行为或…

IMX6ULL_Pro网卡配置

(15条消息) 【IMX6ULL_Pro板卡学习】配置 VMware 使用双网卡_vmware配置双网卡_爱学习的小莲的博客-CSDN博客https://blog.csdn.net/qq_52201194/article/details/127474352?ops_request_misc%257B%2522request%255Fid%2522%253A%2522168223524716800182730924%2522%252C%2522…

Windows逆向安全(一)之基础知识(十一)

二维数组 二维数组初始化 int arr[3][4]{{1,2,3,4},{5,6,7,8},{9,10,11,12} };查看反汇编 7: int arr[3][4]{ 8: {1,2,3,4}, 0040D498 mov dword ptr [ebp-30h],1 0040D49F mov dword ptr [ebp-2Ch],2 0040D4A6 mov dword …

CentOS(linux)使用Docker安装nacos

1. 拉取nacos镜像 docker pull nacos/nacos-server:2.0.3 2. 创建所需文件夹(以安装在home目录下为例) 1) 创建conf文件夹 mkdir -p /home/nacos/conf a. 新增文件application.properties(或者不增加该文件,会使用默认的) 文件内容如下: # spring server.servlet.contextP…