C++入门指南(中)

news2025/2/23 7:07:39


目录

​编辑

一、C++关键字(C++98)

二、命名空间

2.1 域

2.2 命名空间域

2.1 命名空间定义

2.2 命名空间使用

三、C++输入&输出

四、缺省参数

4.1 缺省参数概念

4.2 缺省参数分类

五、函数重载

5.1 函数重载概念

5.2 C++支持函数重载的原理--名字修饰(name Mangling)


一、C++关键字(C++98)

        C++兼容C语言,所以在C语言的基础上又增添了许多的关键字。C语言有32个关键字,而C++总计63个关键字,差不多是C语言的2倍。

二、命名空间

2.1 域

在C++中,域是指变量、函数、类等标识符的可见性和生存期,主要有以下几种类型的域:

  1. 全局域:全局域是指在全局范围内声明的标识符,可以在整个程序中访问。全局域中的标识符在程序开始时创建,在程序结束时销毁。
  2. 局部域:局部域是指在函数或代码块内部声明的变量的作用域。局部域中的变量只能在声明它们的函数或代码块内部访问,超出该范围就会被销毁。
  3. 命名空间域:命名空间是一种将标识符组织在一起以避免命名冲突的机制。在命名空间中声明的标识符具有命名空间域,只能在该命名空间内访问。
  4. 类域:类域是指在类定义中声明的成员变量和成员函数的作用域。类域中的成员变量和成员函数只能在类的成员函数内部或通过类的对象访问。

域作用限定符:

        在C++中,域作用限定符用于指定变量、函数或类成员所属的域或命名空间。域作用限定符使用双冒号符号 “::” ,其语法格式为:

//指定变量所属的命名空间
namespace_name::variable_name;

//指定函数所属的命名空间
namespace_name::function_name();

//指定类成员变量所属的类
class_name::member_variable;

//指定类成员函数所属的类
class_name::member_function();

示例:

#include <iostream>

namespace A {
	int num = 10;
}

namespace B {
	int num = 20;
}

//编译器使用变量或函数时的搜索原则:
//1.如果不指定域,先在局部域搜索
//2.再去全局域搜索
//3.如果指定域,就直接去指定域搜索
int main()
{
	//输出10,指定变量num属于命名空间A
	std::cout << A::num << std::endl;

	//输出20,指定变量num属于命名空间B
	std::cout << B::num << std::endl;

	return 0;
}


我们再来看看下面这段代码:

int x = 1;

int main()
{
	int x = 0;
	printf("%d\n", x);

	return 0;
}

毫无疑问,程序的输出结果为 0 ,那怎么样才能让程序输出 1 呢? 

其实非常简单,我们只需要在x的前面加上域作用限定符:: 左边不指定,就默认访问全局域中的变量。

int x = 1;

int main()
{
	int x = 0;
	printf("%d\n", x);
	printf("%d\n", ::x);

	return 0;
}

2.2 命名空间域

        在C/C++中,变量、函数和后面要学到的类都是大量存在的,这些变量、函数和类的名称将都存在于全局作用域中,可能会导致很多冲突。使用命名空间的目的是对标识符的名称进行本地化以避免命名冲突或名字污染namespace关键字的出现就是针对这种问题的。

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

int rand = 10;

//因为rand(用来生成随机数)是函数名,现在将它定义为全局变量
//会和库里边的函数产生命名冲突
//C语言没办法解决类似这样的命名冲突问题,所以C++提出了namespace来解决
int main()
{
	printf("%d\n", rand);

	return 0;
}

2.1 命名空间定义

        定义命名空间,需要使用到namespace关键字,后面跟命名空间的名字,然后接一对{ }即可,{ }中即为命名空间的成员。

// Lv是命名空间的名字,一般开发中是用项目名字做命名空间名。

// 1. 正常的命名空间定义
namespace Lv 
{
	//命名空间中可以定义变量/函数/类型
	int rand = 10;

	int Add(int left, int right)
	{
		return left + right;
	}

	struct Node
	{
		struct Node* next;
		int val;
	};
}

//2. 命名空间可以嵌套
// test.cpp
namespace N1
{
	int a;
	int b;
	int Add(int left, int right)
	{
		return left + right;
	}
	namespace N2
	{
		int c;
		int d;
		int Sub(int left, int right)
		{
			return left - right;
		}
	}
}

//3. 同一个工程中允许存在多个相同名称的命名空间,编译器最后会合成同一个命名空间中。
// ps:一个工程中的test.h和上面test.cpp中两个N1会被合并成一个
// test.h
namespace N1
{
	int Mul(int left, int right)
	{
		return left * right;
	}
}

🌴注意:

一个命名空间就定义了一个新的作用域,命名空间中的所有内容都局限于该命名空间中。

2.2 命名空间使用

🍂命名空间中成员该如何使用呢?比如:

#include <iostream>

namespace N
{
	//命名空间中可以定义变量/函数/类型
	int a = 0;
    int b = 1;

	int Add(int left, int right)
	{
		return left + right;
	}

	struct Node
	{
		struct Node* next;
		int val;
	};
}

int main()
{
	// 编译报错:error C2065: “a”: 未声明的标识符
	printf("%d\n", a);

	return 0;
}

🍂命名空间的使用有三种方式:

🌴加命名空间名称及作用域限定符

int main()
{
	printf("%d\n", N::a);

	return 0;
}

🌴使用using将命名空间中某个成员引入

using N::b;
int main()
{
	printf("%d\n", N::a);
	printf("%d\n", b);

	return 0;
}

🌴使用using namespace 命名空间名称引入

using namespace N;
int main()
{
	printf("%d\n", N::a);
	printf("%d\n", b);
	Add(10, 20);

	return 0;
}

三、C++输入&输出

#include<iostream>
// std是C++标准库的命名空间名,C++将标准库的定义实现都放到这个命名空间中
using namespace std;

int main()
{
	cout << "Hello world!!!" << endl;

	return 0;
}

说明:

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

注意:

        早期标准库将所有功能在全局域中实现,声明在.h后缀的头文件中,使用时只需包含对应头文件即可,后来将其实现在std命名空间下,为了和C头文件区分,也为了正确使用命名空间,规定C++头文件不带.h;旧编译器(vc 6.0)中还支持<iostream.h>格式,后续编译器已不支持,因此推荐使用<iostream>+std的方式。

#include <iostream>
using namespace std;

int main()
{
	int a;
	double b;
	char c;

	// 可以自动识别变量的类型
	cin >> a;
	cin >> b >> c;

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

	return 0;
}

std命名空间的使用惯例:

std是C++标准库的命名空间,如何展开std使用更合理呢?

  • 在日常练习中,建议直接using namespace std即可,这样就很方便。
  • using namespace std展开,标准库就全部暴露出来了,如果我们定义跟库重名的类型/对象/函数,就存在冲突问题。该问题在日常练习中很少出现,但是项目开发中代码较多、规模较大,就很容易出现问题。所以建议在项目开发中使用像std::cout这样的格式,使用时指定命名空间 +using std::cout展开常用的库对象/类型等方式。

四、缺省参数

4.1 缺省参数概念

        缺省参数是声明或定义函数时为函数的参数指定一个缺省值。在调用该函数时,如果没有指定实参则采用该形参的缺省值,否则使用指定的实参。

#include <iostream>
using namespace std;

void Func(int a = 0)
{
	cout << a << endl;
}

int main()
{
	Func(); // 没有传参时,使用参数的默认值
	Func(10); // 传参时,使用指定的实参

	return 0;
}

4.2 缺省参数分类

  • 🌴全缺省参数
#include <iostream>
using namespace std;

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

int main()
{
	Func(); // 没有传参时,使用参数的默认值
	Func(100); // 传参时,使用指定的实参

	return 0;
}

  • 🌴半缺省参数
#include <iostream>
using namespace std;

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

int main()
{
	Func(10, 20, 30);
	Func(10, 20);
	Func(100); 

	return 0;
}

注意:

  • 半缺省参数必须从右往左依次来给出,不能间隔着给。
  • 缺省参数不能在函数声明和定义中同时出现。通常出现在声明中,因为编译器在“编译”阶段会检查语法,如果出现在定义中,编译器就会报错。
//a.h
void Func(int a = 10);
// a.cpp
void Func(int a = 20)
{}
// 注意:如果声明与定义位置同时出现,恰巧两个位置提供的值不同,那编译器就无法确定到底该
用那个缺省值。
  •  缺省值必须是常量或者全局变量。
  • C语言不支持(编译器不支持)。

五、函数重载

自然语言中,一个词可以有多重含义,人们可以通过上下文来判断该词真实的含义,即该词被重载了。

比如:
        刚刚翻看儿子的作业,有一道题要求用“一边······一边······"造句。他写的是:一对男女在打架,我不知道该帮谁,因为一边是爸爸,一边是妈妈。

        这是《读者》杂志的一则笑话。”一边······一边“连起来用,表示一个动作与另一个动作同时进行,这里的”一边“是副词,但是,”一边“还可以做方位名词,表示某个地方。

5.1 函数重载概念

函数重载:是函数的一种特殊情况,C++允许在同一作用域中声明几个功能类似的同名函数,这些同名函数的形参列表(参数个数类型类型顺序)不同,常用来处理实现功能类似、数据类型不同的问题。

#include <iostream>
using namespace std;

// 1、参数类型不同
int Add(int left, int right)
{
	cout << "int Add(int left, int right)" << endl;
	return left + right;
}
double Add(double left, double right)
{
	cout << "double Add(double left, double right)" << endl;
	return left + right;
}

// 2、参数个数不同
void f()
{
	cout << "f()" << endl;
}
void f(int a)
{
	cout << "f(int a)" << endl;
}

// 3、参数类型顺序不同
void f(int a, char b)
{
	cout << "f(int a,char b)" << endl;
}
void f(char b, int a)
{
	cout << "f(char b, int a)" << endl;
}

int main()
{
	Add(10, 20);
	Add(10.1, 20.2);

	f();
	f(10);

	f(10, 'a');
	f('a', 10);

	return 0;
}

5.2 C++支持函数重载的原理--名字修饰(name Mangling)

为什么C++支持函数重载,而C语言不支持函数重载呢?

在C/C++中,一个程序要运行起来,需要经历以下几个阶段:预处理、编译、汇编、链接。

【PS:有忘记的小伙伴可以参考博主的另一篇文章:程序环境和预处理


 

1. 实际项目通常是由多个头文件和多个源文件构成,而通过C语言阶段学习的编译链接,我们可以知道,【当前a.cpp中调用了b.cpp中定义的Add函数时】,编译后链接前,a.o的目标文件中没有Add的函数地址,因为Add是在b.cpp中定义的,所以Add的地址在b.o中。那么怎么办呢?

2. 所以链接阶段就是专门处理这种问题,链接器看到a.o调用Add,但是没有Add的地址,就会到b.o的符号表中找Add的地址,然后链接到一起。

3. 那么链接时,面对Add函数,链接接器会使用哪个名字去找呢?这里每个编译器都有自己的函数名修饰规则。

4. 由于Windows下vs的修饰规则过于复杂,而Linux下g++的修饰规则简单易懂,所以下面我们使用g++演示这个修饰后的名字。

5. 通过下面我们可以看出gcc的函数修饰后名字不变。而g++的函数修饰后变成【_Z+函数长度+函数名+类型首字母】

  •  🌴采用C语言编译器编译后结果

结论:在linux下,采用gcc编译完成后,函数名字的修饰没有发生改变。

  •   🌴采用C++编译器编译后结果

结论:在linux下,采用g++编译完成后,函数名字的修饰发生改变,编译器将函数参数类型信息添加到修改后的名字中。 

  • 🌴Windows下名字修饰规则

 

6. 通过这里就理解了C语言没办法支持重载,因为同名函数没办法区分。而C++是通过函数修饰规则来区分,只要参数不同,修饰出来的名字就不一样,就支持了重载。

7. 如果两个函数函数名和参数是一样的,返回值不同是不构成重载的,因为调用时编译器没办法区分。

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

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

相关文章

x264 帧类型决策模块 x264_slicetype_analyse 函数原理分析

======================================================================== ======================================================================== x264帧类型决策 x264 的帧类型决策可以参考:

嵌入式学习第三十三天!(二叉树)

1. 树的概念&#xff1a; 1. 树&#xff1a;由n个结点组成的有限集&#xff0c;有且只有一个根结点&#xff08;由根结点可以访问后继结点&#xff09;&#xff0c;其他结点只有一个前驱结点&#xff0c;但可以有多个后继结点&#xff08;一对多&#xff09;。当n 0时&#xf…

ST表(静态RMQ问题)

static Range Max/Min Query ST表 利用的是动态规划的思想 状态&#xff1a; //st[i][j]-->区间长度为1<<j&#xff0c;在区间[i,i1<<j-1]上的最值 状态转移方程&#xff1a; st[i][j]max(st[i][j-1],st[i(1<<j-1)][j-1]);#include <iostream> #inc…

基于51单片机的传送带调速产品计数proteus仿真设计+程序+设计报告+原理图+讲解视频

这里写目录标题 1. 主要功能&#xff1a;2. 讲解视频&#xff1a;3. 仿真4. 程序代码5. 设计报告6. 原理图7. 设计资料内容清单&&下载链接资料下载链接&#xff08;可点击&#xff09;&#xff1a; 基于51单片机传送带计数仿真设计( proteus仿真程序设计报告原理图讲解…

processing完整教程

概述&#xff1a;processing在我眼里就是libgdx的高度封装&#xff0c;如果各位会libgdx&#xff0c;学processing应该可以说是无师自通&#xff0c;当然processing是java语言那边的。 processing是什么&#xff1f; 官网是这样解释的&#xff1a;Processing 是一本灵活的软件…

电脑配置不足的情况下,如何高效运行ANSYS?

ANSYS是一款功能强大的工程仿真软件&#xff0c;它对电脑配置有较高的要求。ANSYS对电脑配置要求高&#xff1f;ansys电脑带不动怎么办&#xff1f;ansys卡住了怎么解决&#xff1f;今天这篇文章一起来看看吧。 当电脑配置不足时&#xff0c;运行ANSYS可能会出现以下情况&…

有必要买超声波洗眼镜机吗?力荐四款实力超群超声波清洗机

在日常生活中&#xff0c;眼镜不仅仅是我们视野的延展&#xff0c;像太阳眼镜&#xff0c;也是有着独特的作用。但是&#xff0c;在每天的使用过程中&#xff0c;眼镜片表面难免会有灰尘&#xff0c;污迹&#xff0c;甚至油渍&#xff0c;这些都会对镜片的材质产生一定的损伤&a…

使用Git管理github的代码库-下

1、打开Git GUI 2、克隆代码库 3、到github代码下载页面&#xff0c;复制链接&#xff08;source location&#xff09; 4、目标路径中src在实际目录中是不存在的&#xff0c;会自动新建&#xff0c;否则会报错 5、添加代码&#xff0c;点击staged changed 6、 commit、push

博客互动革命:如何打造活跃读者社区并提升参与度

CSDN 的朋友你们好&#xff0c;我是未来&#xff0c;今天给大家带来专栏【程序员博主教程&#xff08;完全指南&#xff09;】的第 10 篇文章“与读者互动”。本文揭示了提升技术博客参与度的秘诀。从评论互动到社交媒体策略&#xff0c;本文将指导你如何建立强大的读者社区。掌…

一个注解实现SpringBoot接口请求数据和返回数据加密,提高系统安全性!

注解实现接口加密 1、前言1.1、前端必看1.2、后端必看 2、后端注解实现2.1、实现流程2.2、开始实现2.2.1、 pom2.2.2、 注解2.2.3、 加密工具类2.2.3、 定义切面(注意切点包名)2.2.4、 定义加密基类与各种入参VO2.2.5、写两个Controller 3、参考文章 1、前言 起因是公司给人开发…

深圳盐田某前沿研究所:OLED透明屏引领未来科技空间

产品&#xff1a;55寸OLED透明屏 项目时间&#xff1a;2024年04月 项目地点&#xff1a;深圳盐田 在科技日新月异的今天&#xff0c;前沿的研究机构不仅追求科研的突破&#xff0c;也在不断探索和尝试将最新科技融入其工作环境之中。深圳盐田的一家前沿研究所便是这一探索的先…

搜维尔科技:Xsens惯性动捕+Manus手套用于游戏开发制作

用户名称&#xff1a;北京源力星聚网络科技有限公司&#xff08;Bilibili控股子公司&#xff09; 主要产品&#xff1a;Xsens MVN link *2 &#xff0c;Manus手套*2 &#xff0c;MVN Animate Pro软件等 使用培训现场 使用2套Xsens MVN link 2副Manus手套Xsens Animate Pro软件…

成都数字产业园深度链接校企双方,共建产学研合作研发中心

在数字经济的浪潮中&#xff0c;企业与学院之间的深度链接显得尤为关键。作为人才输送的源头&#xff0c;学院承载着为社会培育高素质人才的使命&#xff1b;而作为创新与实践的基地&#xff0c;企业则渴望吸引这些新鲜血液&#xff0c;为自身的持续发展注入新的活力。近日&…

Adobe使用常见问题解答,如何续费?

“Adobe系统状态”页上的颜色表示什么&#xff1f; Gray表示我们调查了潜在的服务中断并确定它没有影响。橙色表示轻微问题。红色表示严重问题。蓝色表示定期维护。绿色表示所有服务均运行正常。 如何查看以前的CSO或CMR&#xff1f; 导航到 https://status.adobe.com.单击所…

超声波清洗机哪个品牌好用?热心推荐四款全能硬核的超声波清洗机

要知道&#xff0c;超声波清洗机的出现&#xff0c;对于那些经常戴眼镜的人来说&#xff0c;无疑是一种让他们解放了双手的清洁工具&#xff0c;由于戴着眼镜久了&#xff0c;就算用水冲洗&#xff0c;也不能够清洁到镜片缝隙里的脏污渍&#xff0c;但是随着时间的推移&#xf…

SAP-CentralFinance - 学习心得3 - 应付账款与物料管理之间的集成

业务示例 工厂 1010 需要轮胎和内胎。负责的采购组织将相应的采购订单交给了某知名供应商。数天之后&#xff0c;先收到了货物&#xff0c;然后收到了发票。 物料管理中的组织单位 物流的中央组织对象为工厂。工厂是公司的运营范围或分支。工厂可以是集中交货仓库、地区销售…

(五)STM32F407 cubemx IIC驱动OLED(3)软件篇

这篇文章主要是个人的学习经验&#xff0c;想分享出来供大家提供思路&#xff0c;如果其中有不足之处请批评指正哈。   废话不多说直接开始主题&#xff0c;本人是基于STM32F407VET6芯片&#xff0c;但是意在你看懂这篇文章后&#xff0c;不管是F1,F4,H7等一系列系统硬件IIC配…

Elastic 基于 RAG 的 AI 助手:利用 LLM 和私有 GitHub 问题分析应用程序问题

作者&#xff1a;来自 Elastic Bahubali Shetti 作为 SRE&#xff0c;分析应用程序比以往更加复杂。 你不仅必须确保应用程序以最佳状态运行以确保良好的客户体验&#xff0c;而且还必须了解某些情况下的内部工作原理以帮助排除故障。 分析基于生产的服务中的问题是一项团队运动…

迷宫中离入口最近的出口

题目链接 迷宫中离入口最近的出口 题目描述 注意点 maze[i][j] 要么是 ‘.’ &#xff0c;要么是 ‘’entrance.length 2entrance 一定是空格子出口的含义是 maze 边界上的空格子entrance格子不算出口 解答思路 广度优先遍历找到走i步时所能到达的所有节点位置&#xff0…

趋势交易如何交易?fpmarkets实例分享

通过之前的文章&#xff0c;各位聪明的投资者想必都已经知道什么是趋势交易了 &#xff01;但是趋势交易如何交易呢&#xff1f;其实很简单&#xff0c;只要理解了趋势交易的信号点以及如何获取的信号就能 很快的掌握如何使用趋势交易进行盈利&#xff0c;下面fpmarkets澳福就和…