【C++】C++入门1.0
鼠鼠最近在学C++,那么好,俺来做笔记了!
目录
1.C++关键字(C++98)
2.命名空间
2.1.命名空间定义
2.2.命名空间的使用
3.C++的输入&&输出
4.缺省参数
4.1缺省参数概念
4.2.缺省参数的分类
5.函数重载
5.1.函数重载概念
5.2.C++支持函数重载的原理--名字修饰(name Mangling)
C++是在C的基础之上,容纳进去了面向对象编程思想,并增加了许多有用的库,以及编程范式 等。本博客介绍的知识点主要是补充C语言语法的不足,以及C++是如何对C语言设计不合理的地方进行优化的,比如:作用 域方面、IO方面、函数方面、指针方面、宏方面等。
1.C++关键字(C++98)
C++总计63个关键字,C语言32个关键字。
本图片是本鼠借鉴别人的劳动成果(其实本鼠的博客很多都是捏)!
本鼠是初学者,肯定介绍不出这些个关键字的所以然来,以后本鼠学习到的话会在后面的博客介绍的捏!
2.命名空间
我们知道在C语言中,在同一个域里面不能有重复的函数名,变量名。例如C语言:
#include <stdio.h>
#include <stdlib.h>
int rand = 10;
// C语言没办法解决类似这样的命名冲突问题,所以C++提出了namespace来解决
int main()
{printf("%d\n", rand);return 0;
}
// 编译后后报错:error C2365: “rand”: 重定义;以前的定义是“函数”
头文件<stdlib.h>中定义过rand是“函数”,并且“函数”rand定义在全局域当中,我们又定义了全局变量rand,导致rand重定义!
但是在C/C++中,变量、函数和后面要学到的类都是大量存在的,这些变量、函数和类的名称将都存 在于全局作用域中,可能会导致很多冲突。所以C++有了命名空间(C语言可没有)。使用命名空间的目的是对标识符的名称进行本地化, 以避免命名冲突或名字污染。namespace关键字的出现就是针对这种问题的。
2.1.命名空间定义
定义命名空间,需要使用到namespace关键字,后面跟命名空间的名字,然后接一对{}即可,{} 中即为命名空间的成员。
注意:以下代码如果写在.c文件中会报错!
1.正常的命名空间定义。
// HD是命名空间的名字,一般开发中是用项目名字做命名空间名
namespace HD
{// 命名空间的成员可以定义变量/函数/类型int rand = 10;int Add(int left, int right){return left + right;}struct LCD{int age;double weight;struct LCD* next;};
}
2. 命名空间可以嵌套。
namespace HD
{int rand = 10;int Add(int left, int right){return left + right;}//嵌套命名空间namespace LCD{int i = 100;struct LCD{int age;double weight;struct LCD* next;};}
}
3. 同一个工程中允许存在多个相同名称的命名空间,编译器最后会合成同一个命名空间中。
例如本鼠有一个工程,工程包含test.cpp和test.h。
在test.cpp中定义了:
namespace HD {int rand = 10;int Add(int left, int right){return left + right;}//嵌套命名空间namespace LCD{int i = 100;struct LCD{int age;double weight;struct LCD* next;};} }
在test.h中定义了:
namespace HD {typedef struct SListNode{int data; struct SListNode* next; }SListNode;char a[] = {'w','x','h','l','c','d'}; }
那么好,神奇的事发生了,一个工程中的test.h和test.cpp中两个HD会被合并成一个 。
再例如本鼠有一个工程,工程包含只test.cpp文件。
在test.cpp中定义了:
namespace HD {int rand = 10;int Add(int left, int right){return left + right;}//嵌套命名空间namespace LCD{int i = 100;struct LCD{int age;double weight;struct LCD* next;};} }namespace HD {typedef struct SListNode{int data; struct SListNode* next; }SListNode;char a[] = {'w','x','h','l','c','d'}; }
那么好,一个上面的两个HD也会被合并成一个 。
注意:
1.一个命名空间就定义了一个新的作用域(命名空间域使用using将命名空间中某个成员引入),命名空间中的所有内容都局限于该命名空间中。
2.局部域和全局域会影响生命周期和访问,而命名空间域只影响访问。如何影响访问?请看下面本鼠介绍的编译器的访问规则。
3.命名空间封装的成员生命周期与全局变量的生命周期是一样的,命名空间定义的变量都是全局变量,所以说命名空间域不影响生命周期。
2.2.命名空间的使用
如何使用命名空间的成员,例如:
#include<stdio.h>
namespace HD
{int rand = 10;int Add(int left, int right){return left + right;}//嵌套命名空间namespace LCD{int i = 100;struct LCD{int age;double weight;struct LCD* next;};}
}int main()
{//编译报错:error C2065: “rand”: 未声明的标识符printf("%d", rand);return 0;
}
这里为什么报错?
不得不提编译器的访问规则:
1.如果没有指定域。优先访问局部域,若没有访问到则访问全局域,若全局域还没有访问到,报错!
2.如果指定了域。直接去指定的域访问,若没有访问到,报错!
这里没有指定域,所以编译器先后去局部域和全局域搜索都搜索不到rand的定义,所以报错!
那么如何解决,有三种办法,请看:
1.加命名空间名称及作用域限定符::
#include<stdio.h>
namespace HD
{int rand = 10;int Add(int left, int right){return left + right;}//嵌套命名空间namespace LCD{int i = 100;struct LCD{int age;double weight;struct LCD* next;};}
}
int main()
{printf("%d\n", HD::rand);printf("%d\n", HD::LCD::i);return 0;
}
作用域限定符:: 就是指定域用的。如果作用域限定符::前面为空,那么默认指定访问全局域,如:
#include<stdio.h>
namespace HD
{int rand = 10;
}
int rand = 100;
int main()
{int rand = 1000;printf("%d\n", HD::rand);printf("%d\n", ::rand);printf("%d\n", rand);return 0;
}
第一个打印10,因为指定了域,所以直接去命名空间域HD搜索了!
第二个打印100,因为指定了域,所以直接去全局域搜索了!
第三个打印1000,因为没有指定域,所以优先访问局部域且访问到了rand。
2. 使用using将命名空间中某个成员引入
#include<stdio.h>
namespace HD
{int rand = 10;int Add(int left, int right){return left + right;}//嵌套命名空间namespace LCD{int i = 100;struct LCD{int age;double weight;struct LCD* next;};}
}
using HD::rand;
using HD::LCD::i;
int main()
{printf("%d\n", rand);printf("%d\n", i);return 0;
}
这个被引入的成员能在编译器访问全局域的时候被访问到!
3.使用using namespace 命名空间名称引入
#include<stdio.h>
namespace HD
{int rand = 10;int Add(int left, int right){return left + right;}//嵌套命名空间namespace LCD{int i = 100;struct LCD{int age;double weight;struct LCD* next;};}
}
using namespace HD;
using namespace HD::LCD;
int main()
{printf("%d\n", rand);printf("%d\n", i);return 0;
}
那么这个命名空间的全部成员都可以在编译器访问全局域的时候被访问到!
本鼠顺便提一嘴,这种方式慎用,因为这样就将命名空间成员全部引入了,那样子命名空间不就形同虚设了咩!!!控制不好很容易导致命名冲突!
介绍完了三种命名空间的使用方法,本鼠考考读者老爷们,下面代码运行结果是什么:
#include<stdio.h>
namespace HD
{int rand = 10;int Add(int left, int right){return left + right;}//嵌套命名空间namespace LCD{int i = 100;struct LCD{int age;double weight;struct LCD* next;};}
}
using namespace HD;
int main()
{int rand=100;printf("%d\n", rand);return 0;
}
本鼠认为结果是打印100。因为即使使用using namespace HD引入,将命名空间HD的成员都引入了。但编译器对于没有指定域的话,优先访问局部域,那么局部域有变量rand的定义当然打印100了。
如果访问局部域没有找到rand的定义,那么编译器会访问全局域。由于使用了using namespace HD引入,所以编译器在访问全局域的时候能访问到命名空间HD的成员rand。
#include<stdio.h>
namespace HD
{int rand = 10;int Add(int left, int right){return left + right;}//嵌套命名空间namespace LCD{int i = 100;struct LCD{int age;double weight;struct LCD* next;};}
}
using namespace HD;
int main()
{int RAND=100;printf("%d\n", rand);return 0;
}
3.C++的输入&&输出
本鼠写一个C++版本的Hello world!来讲解:
#include<iostream>
// std是C++标准库的命名空间名,C++将标准库的定义实现都放到这个命名空间中
using namespace std;
int main()
{cout << "Hello world!" << endl;return 0;
}
要看懂这个代码,要了解:
1.std是C++标准库的命名空间名,C++将标准库的定义实现都放到这个命名空间中。
2.cout和cin是全局的流对象,endl是特殊的C++符号,表示换行输出,他们都包含在包含< iostream >头文件中。
3.cout标准输出对象(控制台)可以笼统认为等于C语言的printf,cin标准输入对象(键盘)可以笼统认为等于C语言的scanf,endl可以笼统认为等于C语言的换行符"\n"。
4.使用cout标准输出对象(控制台)和cin标准输入对象(键盘)时,必须包含< iostream >头文件以及按命名空间使用方法使用std。
5.C++中<<是流插入运算符,>>是流提取运算符。当然C++兼容C语言的大部分语法,所以<<在C++中也可以是左移操作符,>>在C++中也可以是右移操作符。
6.使用C++输入输出更方便,不需要像printf/scanf输入输出时那样,需要手动控制格式。 C++的输入(cin)输出(cout)可以自动识别变量类型。
那么看完上面6点,看结果:
其实很形象的,”Hello world!“ 和endl依次顺着<<”流入“cout打印在控制台上咩!
我们看到打印"Hello world!"并不用像C语言那样手动控制格式“%s”,自动识别了!
注意:早期标准库将所有功能在全局域中实现,声明在.h后缀的头文件中,使用时只需包含对应 头文件即可,后来将其实现在std命名空间下,为了和C头文件区分,也为了正确使用命名空间, 规定C++头文件不带.h;旧编译器(vc 6.0)中还支持格式,后续编译器已不支持,因 此推荐使用+std的方式。
std命名空间的使用惯例: std是C++标准库的命名空间,如何展开std使用更合理呢?
1. 在日常练习中,建议直接using namespace std即可,这样就很方便。
2. using namespace std展开,标准库就全部暴露出来了,如果我们定义跟库重名的类型/对 象/函数,就存在冲突问题。该问题在日常练习中很少出现,但是项目开发中代码较多、规模 大,就很容易出现。所以建议在项目开发中使用,像std::cout这样使用时指定命名空间 + using std::cout展开常用的库对象/类型等方式。
4.缺省参数
4.1缺省参数概念
缺省参数(或者叫默认参数)是声明或定义函数时为函数的参数指定一个缺省值。在调用该函数时,如果没有指定实 参则采用该形参的缺省值,否则使用指定的实参。
#include<iostream>
using namespace std;
void Func(int a = 10)
{cout << a << endl;
}
int main()
{Func();// 没有传参时,使用参数的缺省值Func(100);// 传参时,使用指定的实参return 0;
}
简单易懂好吧!
缺省参数有几点注意事项:
1.缺省参数不能在函数声明和定义中同时出现,当函数声明和定义分离时在声明给缺省参数。
2.缺省值必须是常量或者全局变量。
3.C语言不支持(编译器不支持)缺省参数。
4.2.缺省参数的分类
1.全缺省参数
就是为函数所有参数指定了一个缺省值,如:
void Func(int a = 10, int b = 20, int c = 30){cout<<"a = "<<a<<endl;cout<<"b = "<<b<<endl;cout<<"c = "<<c<<endl;}
2.半缺省参数
就是为函数部分参数指定了一个缺省值,如:
void Func(int a, int b = 10, int c = 20){cout<<"a = "<<a<<endl;cout<<"b = "<<b<<endl;cout<<"c = "<<c<<endl;}
要注意半缺省参数必须从右往左依次来给出,不能间隔着给 。
调用一个看看:
#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;
}
int main()
{Func(1,10);return 0;
}
这里函数Func参数a没有指定缺省值,所有调用Func函数的时候必须给a一个实参,b、c随便。
5.函数重载
5.1.函数重载概念
C语言不支持同名函数,但是C++支持。因为C++有:
函数重载:是函数的一种特殊情况,C++允许在同一作用域中声明几个功能类似的同名函数,这 些同名函数的形参列表(参数个数或类型或类型顺序)不同,常用来处理实现功能类似数据类型不同的问题。
1.参数类型不同构成函数重载
#include<iostream>
using namespace std;
int Add(int a = 10, int b = 20)
{cout << "Add(int a=10,int b=20)->";return a + b;
}
double Add(double a = 10.0, double b = 10.0)
{cout << "Add(double a=10.0,double b=10.0)->";return a + b;
}
int main()
{cout << Add(5, 5) << endl;cout << Add(10.0, 9.9) << endl;return 0;
}
编译器会根据传入实参类型不同调用相应的Add函数。
2.参数个数不同构成函数重载
#include<iostream>
using namespace std;
void Func(int a,int b)
{cout << "Func(int a,int b)"<<endl;}
void Func(int a,int b,int c)
{cout << "Func(int a,int b,int c)"<<endl;
}
int main()
{Func(1, 2);Func(1, 2, 3);return 0;
}
编译器会根据传入实参个数不同调用相应Func函数。
3.参数类型顺序不同构成函数重载
#include<iostream>
using namespace std;
void Func(int a,double b)
{cout << "Func(int a,double b)"<<endl;}
void Func(double a,int b)
{cout << "Func(double a,int b)"<<endl;
}
int main()
{Func(1, 2.2);Func(1.1, 2);return 0;
}
编译器会根据传入实参类型顺序不同调用相应Func函数。
5.2.C++支持函数重载的原理--名字修饰(name Mangling)
本鼠也说不是很清楚,本鼠大概知道原理。所以本鼠大概讲讲,如有不足,恳请斧正!
在C/C++中,一个程序要运行起来,需要经历以下几个阶段:预处理、编译、汇编、链接。
C语言编译器在链接时,直接根据函数名去找函数地址。由于函数名相同,导致找到多个地址,编译器不知道该链接哪一个地址,所以不支持函数重载。
C++编译器有函数名修饰规则(这个规则不统一,各个编译器可能不同),会引入函数参数类型信息添加到修改后的函数名中,只要参数不同,修饰出来的名字就不一样,那么找到的地址就不同,就支持函数重载了!
本博客就到这里吧,感谢阅读,下次再见!
相关文章:

【C++】C++入门1.0
鼠鼠最近在学C,那么好,俺来做笔记了! 目录 1.C关键字(C98) 2.命名空间 2.1.命名空间定义 2.2.命名空间的使用 3.C的输入&&输出 4.缺省参数 4.1缺省参数概念 4.2.缺省参数的分类 5.函数重载 5.1.函数重载概念 5.2.C支持函数…...

springboot实现文件上传功能,整合云服务
文章目录 这是springboot案例的,文件上传功能的拆分,本篇将带大家彻底了解文件上传功能,先从本地存储再到云存储,全网最详细版本,保证可以学会,可以了解文件上传功能的开发文件上传功能剖析进行书写一个小的文件上传文件上传的文件三要素首先表单提交的方式要是 post方式,第二个…...

接口interfance的基本使用
一.为什么有接口? 接口:就是一种规则。 二.接口的定义和使用 1.接口用关键字interface来定义 public interface 接口名{} 2.接口不能实例化 3.接口和类之间是实现关系,通过implements关键字表示 4.接口的子类(实现类) 注意1: 接口和类的实现关系…...

Gitlub如何删除分支(删除远程分支+本地分支)
目录 背景 删除方法 总结 背景 想要删除自己在本地创建的并已上传到远程分支中的分支。 删除方法 1)删除远程分支 git push origin --delete brannchname 2)删除本地分支 先切换到其他分支 git checkout otherbranch 删除本地分支 git bran…...

使用RSA算法加密字符串:从基础到实现 - Python
在现代数据安全中,加密算法起着至关重要的作用。特别是非对称加密算法,如RSA(Rivest-Shamir-Adleman),广泛应用于保护敏感信息的传输。本文将详细介绍如何使用RSA算法加密和解密字符串,包括生成密钥对、加密…...

MFC实现守护进程,包括开机自启动、进程单例、进程查询、进程等待、重启进程、关闭进程
在Windows平台上实现一个守护进程,由于与系统有关,所有使用MFC来实现是最合适的,被守护的进程则不限语言。废话不多,直接开整。 目录 1. 开机自启动 2. 进程单例 3. 进程查询 4. 进程等待 5. 重启进程 6. 关闭进程 7、最后…...

Spark SQL数据源 - Parquet文件
当使用Spark SQL处理Parquet文件时,你可以使用spark.read.parquet()方法从文件系统中加载Parquet数据到一个DataFrame中。Parquet是一种列式存储格式,非常适合用于大数据集,因为它提供了高效的压缩和编码方案。 以下是一个简单的例子&#x…...

eNsp——两台电脑通过一根网线直连通信
一、拓扑结构 二、电脑配置 ip和子网掩码,配置两台电脑处于同一网段 三、测试 四、应用 传文件等操作,可以在一台电脑上配置FTP服务器...

杂牌记录仪TS视频流恢复方法
大多数的记录仪都采用了MP4/MOV文件方案,极少数的可能在用AVI文件,极极少数的在用TS文件方案。很多人可能不太解TS文件,这是一种古老的视频文件结构,下边这个案例我们来看下TS视频文件的恢复方法。 故障存储:8G存储卡/fat32文件系…...

十_信号7-信号集
int sigemptyset(sigset_t *set); 清空信号集 int sigfillset(sigset_t *set); 填充满 信号集 int sigaddset(sigset_t *set, int signum); 向信号集中添加信号 int sigdelset(sigset_t *set, int signum); 从型号集中删除信号 int sigismember(const sigset_t *set, int s…...

GPT-4o
微软最新发布的CopilotPC采用了OpenAI最新的GPT-4o技术,新增了多项强大功能。以下是主要的新增功能: 更强大的AI处理能力:CopilotPC采用了专门用于AI处理的特殊芯片,使得电脑能够处理更多的人工智能任务,而无需调用云…...

32位与64位程序下函数调用的异同——计科学习中缺失的内容
前言 今天,通过一个有趣的案例,从反编译的角度看一下C语言中函数参数是如何传递的。 创建main.c文件,将下面实验代码拷贝到main.c文件中。 # main.c #include <stdio.h>int test(int a, int b, int c, int d, int e, int f, int g, …...

Python爬虫实战(实战篇)—16获取【百度热搜】数据—写入Ecel(附完整代码)
文章目录 专栏导读背景结果预览1、爬取页面分析2、通过返回数据发现适合利用lxmlxpath3、继续分析【小说榜、电影榜、电视剧榜、汽车榜、游戏榜】4、完整代码总结 专栏导读 🔥🔥本文已收录于《Python基础篇爬虫》 🉑🉑本专栏专门…...

js切割数组的两种方法slice(),splice()
slice() 返回一个索引和另一个索引之间的数据(不改变原数组),slice(start,end)有两个参数(start必需,end选填),都是索引,返回值不包括end 用法和截取字符串一样 splice() 用来添加或者删除数组的数据,只返回被删除的数据,类型为数组(改变原数组) var heroes["李白&q…...

【计算机毕设】基于SpringBoot的医院管理系统设计与实现 - 源码免费(私信领取)
免费领取源码 | 项目完整可运行 | v:chengn7890 诚招源码校园代理! 1. 研究目的 本项目旨在设计并实现一个基于SpringBoot的医院管理系统,以提高医院管理效率,优化医疗服务流程,提升患者就诊体验…...

导线防碰撞警示灯:高压线路安全保障
导线防碰撞警示灯:高压线路安全保障 在广袤的大地上,高压线路如同血脉般纵横交错,然而,在这看似平静的电力输送背后,却隐藏着不容忽视的安全隐患。特别是在那些输电线路跨越道路、施工等区域的路段,线下超…...

【LeetCode 77. 组合】
1. 题目 2. 分析 本题有个难点在于如何保存深搜得到的结果?总结了一下,深搜处理的代码,关于返回值有三大类。 第一类:层层传递,将最深层的结果传上来;这类题有:【反转链表】 第二类࿱…...

element-ui组件table去除下方滚动条,实现鼠标左右拖拽移动表格
时隔多日,再次遇到值得记录的问题。 需求 项目前端使用vue框架,页面使用element-ui进行页面快速搭建。默认的table组件当表格过长时,下方会出现横向的滚动条,便于用户对表格进行左右滑动。考虑到页面美观问题,滚动条…...

【C++】list的使用(上)
🔥个人主页: Forcible Bug Maker 🔥专栏: STL || C 目录 前言🌈关于list🔥默认成员函数构造函数(constructor)析构函数(destructor)赋值运算符重载 …...

【代码随想录训练营】【Day 37】【贪心-4】| Leetcode 840, 406, 452
【代码随想录训练营】【Day 37】【贪心-4】| Leetcode 840, 406, 452 需强化知识点 python list sort的高阶用法,两个key,另一种逆序写法python list insert的用法 题目 860. 柠檬水找零 思路:注意 20 块找零,可以找3张5块升…...

concat是什么?前端开发者必须掌握的数组拼接利器
concat是什么?前端开发者必须掌握的数组拼接利器 在前端开发中,concat是一个极其重要的概念,它能够帮助我们实现数组之间的无缝拼接。那么,concat到底是什么?为什么它在前端开发中如此重要?接下来…...

WHAT - 容器化系列(一)
这里写目录标题 一、什么是容器与虚拟机1.1 什么是容器1.2 容器的特点1.3 容器和虚拟机的区别虚拟机(VM):基于硬件的资源隔离技术容器:基于操作系统的资源隔离技术对比总结应用场景 二、容器的实现原理1. Namespace(命…...

QT7_视频知识点笔记_67_项目练习(页面以及对话框的切换,自定义数据类型,DB数据库类的自定义及使用)
视频项目:7----汽车销售管理系统(登录,品牌车管理,新车入库,销售统计图表)-----项目视频没有,代码也不全,更改项目练习:学生信息管理系统。 学生信息管理系统࿱…...

windows10系统64位安装delphiXE11.2完整教程
windows10系统64位安装delphiXE11.2完整教程 https://altd.embarcadero.com/download/radstudio/11.0/radstudio_11_106491a.iso XE11.1 https://altd.embarcadero.com/download/radstudio/11.0/RADStudio_11_2_10937a.iso XE11.2 关键使用文件在以下内容:windows10…...

09.责任链模式
09. 责任链模式 什么是责任链设计模式? 责任链设计模式(Chain of Responsibility Pattern)是一种行为设计模式,它允许将请求沿着处理者对象组成的链进行传递,直到有一个处理者对象能够处理该请求为止。这种模式的目的…...

Amazon云计算AWS(一)
目录 一、基础存储架构Dynamo(一)Dynamo概况(二)Dynamo架构的主要技术 二、弹性计算云EC2(一)EC2的基本架构(二)EC2的关键技术(三)EC2的安全及容错机制 提供的…...

十_信号4-SIGCHLD信号
SIGCHLD信号 在学习进程控制的时候,使用wait和waitpid系统调用何以回收僵尸进程,父进程可以阻塞等待,也可以非阻塞等待,采用轮询的方式不停查询子进程是否退出。 采用阻塞式等待,父进程就被阻塞了,什么都干…...

HCIP的学习(27)
RSTP—802.1W—快速生成树协议 STP缺陷: 1、收敛速度慢----STP的算法是一种被动的算法,依赖于计时器来进行状态变化 2、链路利用率低 RSTP向下兼容STP协议。(STP不兼容RSTP) 改进点1—端口角色 802.1D协议---根端口、指定端口…...

6. MySQL 查询、去重、别名
文章目录 【 1. 数据表查询 SELECT 】1.1 查询表中所有字段使用 * 查询表的所有字段列出表的所有字段 1.2 查询表中指定的字段 【 2. 去重 DISTINCT 】【 3. 设置别名 AS 】3.1 为表指定别名3.2 为字段指定别名 【 5. 限制查询结果的条数 LIMIT 】5.1 指定初始位置5.2 不指定初…...

Oracle导出clob字段到csv
使用UTL_FILE ref: How to Export The Table with a CLOB Column Into a CSV File using UTL_FILE ?(Doc ID 1967617.1) --preapre data CREATE TABLE TESTCLOB(ID NUMBER, MYCLOB1 CLOB, MYCLOB2 CLOB ); INSERT INTO TESTCLOB(ID,MYCLOB1,MYCLOB2) VALUES(1,Sample row 11…...