C++入门指南(中)


目录

​编辑

一、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属于命名空间Astd::cout << A::num << std::endl;//输出20,指定变量num属于命名空间Bstd::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.mzph.cn/pingmian/11257.shtml

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

相关文章

告别黑板粉笔 高新技术进课堂 未来教室会成什么

现在&#xff0c;全国许多院校都经过引进信息化技能&#xff0c;完成智慧校园建造&#xff0c;推进教育均衡展开。一些校园的小学教室的信息化配备投入经费已达50万元/每间&#xff0c;初中是70万元&#xff0c;高中是90万元。这些新技能的投入运用有用的共享教育内容、精准地分…

基于select for update 实现数据库分布式锁

1、select for update 的基本语法 SELECT * FROM table_name WHERE condition FOR UPDATE;2、select for update 的定义及作用 2.1 、select for update的含义是在查询数据的同时对所选的数据行进行锁定&#xff0c;以保证数据的一致性和并发控制。在并发环境下&#xff0c;多…

ES6 笔记02

目录 01 对象的扩展 02 链判断运算符 03 属性名表达式 04 Symbol 类型 05 set集合的使用 06 Map集合的使用 07 Set集合和Map集合的遍历方式 08 iterator迭代器 01 对象的扩展 对象的属性和方法的简洁表示: es6允许在字面量对象里面直接写变量名 let 变量名变量值; let …

金融业开源软件应用 评估规范

金融业开源软件应用 评估规范 1 范围 本文件规定了金融机构在应用开源软件时的评估要求&#xff0c;对开源软件的引入、维护和退出提出了实现 要求、评估方法和判定准则。 本文件适用于金融机构对应用的开源软件进行评估。 2 规范性引用文件 下列文件中的内容通过文中的规范…

WS2811 单线 256 级灰度三通道恒流 LED 驱动器芯片 IC

产品概述 WS2811 是三通道LED驱动控制专用电路&#xff0c;芯片内部包含了智能数字接口数据锁存信号整形放大驱动电路&#xff0c;还包含有高精度的内部振荡器和15V高压可编程定电流输出驱动器。同时&#xff0c;为了降低电源纹波&#xff0c;3个通道有一定的延时导通功…

【数据结构课程学习】:队列学习

&#x1f381;个人主页&#xff1a;我们的五年 &#x1f50d;系列专栏&#xff1a;数据结构课程学习 &#x1f337;追光的人&#xff0c;终会万丈光芒 &#x1f389;欢迎大家点赞&#x1f44d;评论&#x1f4dd;收藏⭐文章 目录 &#x1f697; 1.队列的基本概念&#xff1a…

软考高级最容易被挂掉的论文,千万别乱写!

高级考生最没把握的科目应该就是论文了&#xff0c;有些考生考了几次都败在论文上了。那么导致论文不合格的写作误区有哪些&#xff1f;最后十多天&#xff0c;该如何准备呢&#xff1f; 常见写作误区 误区一&#xff1a;偏题 在论文写作时不能偏题&#xff0c;要紧扣子题干…

Visual Studio构建NodeJS原生代码在Electron中的报错问题

文章目录 对比NODE-GYP工具解决问题进一步研究win_delay_load_hook.cc代码MAC中是不需要这个东西的这个标题有点长,相对是一个比较具体的场景,但是这个问题在我自己的实际开发中,确实困扰了我一段时间。 因为在windows下做设备驱动,上位机的开发中。Visual Studio是一个比较…

要想通过等保测评,这7个问题你必须了解

1.什么是等级保护测评&#xff1f; 2.为什么要做等级保护测评&#xff1f; 3.等保1.0与2.0的区别在哪里&#xff1f; 4.等级保护测评参考标准有哪些&#xff1f; 5.等级保护测评的级别有哪些以及哪些系统需要&#xff1f; 6.等保测评的主要内容是什么&#xff1f; 7.等级…

如何利用代理IP高效采集全球热点,赋能短视频创作?

如何利用代理IP高效采集全球热点&#xff0c;赋能短视频创作&#xff1f; 一、摘要二、代理IP1. 什么是代理IP&#xff1f;2. 代理IP的分类3. 代理的重要性 三、如何选择可靠的代理IP服务商&#xff1f;四、IPIDEA代理IP简介1.IPIDEA简介2.IPIDEA的优势 五、获取代理IP1. 注册平…

python随机显示四级词汇

python实现一个浮动窗口随机显示四级单词在桌面跑来跑去 实现一个浮动窗体随机显示四级单词在windows桌面置顶移动 tkinter库来创建窗口和显示单词&#xff0c;以及random库来随机选择单词。 使用after方法来定时更新窗口的位置&#xff0c;实现单词窗口的慢慢移动效果 使用…

有机硅改性氟树脂性能进一步提升 市场需求增长空间大

有机硅改性氟树脂性能进一步提升 市场需求增长空间大 有机硅改性氟树脂&#xff0c;利用有机硅树脂对氟树脂进行改性得到一种新型的、性能更为优异的树脂材料。 有机硅树脂&#xff0c;具有柔韧性好、电绝缘、憎水、耐候、耐老化等优点&#xff0c;但固化温度高且时间长、附着力…

使用Apache Spark从MySQL到Kafka再到HDFS的数据转移

使用Apache Spark从MySQL到Kafka再到HDFS的数据转移 在本文中&#xff0c;将介绍如何构建一个实时数据pipeline&#xff0c;从MySQL数据库读取数据&#xff0c;通过Kafka传输数据&#xff0c;最终将数据存储到HDFS中。我们将使用Apache Spark的结构化流处理和流处理功能&#…

MySQL中表的插入,修改,删除语法

插入 插入数据有四种方法,代码如下 -- 给表中添加元素 -- insert into 表名 (列名) values(数据)INSERT INTO student(NAME,gender,birthday,phone)VALUES(张三,男,2003-2-10,13333333333) INSERT INTO student(NAME,gender,birthday,phone,address,height,rig_time) VALUES(…

在Mac环境下打包Python应用

1、创建虚拟环境 conda create -n ur_name python3.7 pip install -r requirement.txt 2、配置文件生成 cd ur_project py2applet --make-setup __main__.py 3、APP打包 # 编辑setup.py文件,具体参考本文文献 python setup.py py2app 用 py2app 将 Python 脚本打包成 Mac…

高级优化理论与方法(十二)

高级优化理论与方法&#xff08;十二&#xff09; LPDuality of LPWeek LP Duality TheoremStrong LP Duality TheoremCorollary Complementary Slackness ConditionRemarksExample Non-Simplex MethodsKhachiyan (Ellipsoid)Karmarkar (Interior point) Integer Linear Progra…

Leetcode-有效的括号

20. 有效的括号 - 力扣&#xff08;LeetCode&#xff09;https://leetcode.cn/problems/valid-parentheses/ 题目 给定一个只包括 (&#xff0c;)&#xff0c;{&#xff0c;}&#xff0c;[&#xff0c;] 的字符串 s &#xff0c;判断字符串是否有效。 有效字符串需满足&…

MongoDB 数据探索之道:查询文档操作详解

在 MongoDB 数据库中&#xff0c;查询文档是一种强大的工具&#xff0c;能够帮助您深入了解数据并提取所需信息。无论是从大型数据集中检索特定记录&#xff0c;还是进行数据统计和分析&#xff0c;查询文档都是不可或缺的。在本指南中&#xff0c;我们将深入探讨 MongoDB 查询…

c++ map,set封装

map 是一个 kv 结构&#xff0c; set 是 k结构。 我们前面模拟实现了 红黑树&#xff0c;但是我们实现的红黑树把 kv 结构写死了&#xff0c;怎么样才能用泛型编程的思想来实现map和set呢 我们先简单看一下原码中是怎么实现的 1.原码实现逻辑 我们打开这里的 stl_set.h 通过…

Dubbo基本使用

Dubbo基本使用 1.项目介绍2.开发步骤2.1 启动注册中心2.2 初始化项目2.3 添加 Maven 依赖2.3.1 父pom.xml2.3.1 consumer模块和provider模块pom.xml 2.4 定义服务接口2.5 定义服务端的实现2.6 配置服务端 Yaml 配置文件2.7 配置消费端 Yaml 配置文件2.8 基于 Spring 配置服务端…