【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.coutcin是全局的流对象,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++编译器有函数名修饰规则(这个规则不统一,各个编译器可能不同),会引入函数参数类型信息添加到修改后的函数名中,只要参数不同,修饰出来的名字就不一样,那么找到的地址就不同,就支持函数重载了!

本博客就到这里吧,感谢阅读,下次再见!

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

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

相关文章

深度学习-04-数值的微分

深度学习-04-数值的微分 本文是《深度学习入门2-自製框架》 的学习笔记&#xff0c;记录自己学习心得&#xff0c;以及对重点知识的理解。如果内容对你有帮助&#xff0c;请支持正版&#xff0c;去购买正版书籍&#xff0c;支持正版书籍不仅是尊重作者的辛勤劳动&#xff0c;也…

所有人都可以做的副业兼职,短剧推广,1天挣几百,附详细方法!

自从上次向大家介绍了短剧掘金项目以来&#xff0c;便陆续收到了众多朋友的询问&#xff1a;现在是否还能加入短剧掘金的大军&#xff1f;答案是肯定的。目前&#xff0c;无论是各大视频平台还是其他渠道&#xff0c;短剧掘金项目都呈现出蓬勃发展的态势。而且&#xff0c;相关…

SSM高校社团管理系统-计算机毕业设计源码86128

目 录 摘要 1 绪论 1.1研究背景与意义 1.2开发现状 1.3研究方法 1.4 ssm框架介绍 1.5论文结构与章节安排 2 高校社团管理系统系统分析 2.1 可行性分析 2.2 系统流程分析 2.2.1数据增加流程 2.2.2数据修改流程 2.2.3数据删除流程 2.3 系统功能分析 2.3.1 功能性分…

QT实现动态翻译切换

1、实现QT动态中英文切换效果 效果如下: 2、原理 因为软件本身就是中文版,所以只需准备一个英文版的翻译即可,,那就是将所有需要翻译的地方用tr包裹,然后首先执行lupdate更新一下,接着用qt的翻译软件 Qt Linguist打开ts文件进行翻译,然后保存,最后使用 lrelease发布一…

位运算专题

常见位运算总结: 1. 基础位运算 << 左移 >> 右移 ~ 按位取反 & 按位与 口诀: 有0则0 | 按位或 口诀: 有1则1 ^ 异或 口诀:相同为0,相异为1 / 无进位相加 2. 位运算的优先级 做题时, 能加括号就加括号, 无需管优先级如何 3. 给一个二进制数n, 确定…

为什么总是卡在验证真人这里无法通过验证?

最近总是在浏览某些网站的时候卡在这个“确认你是真人”的验证页面&#xff0c;无法通过真人验证&#xff0c;这是怎么回事儿&#xff1f;如何解决呢&#xff1f; 首先&#xff0c;出现这个“确认您是真人”的验证一般都是这个网站使用了 CloudFlare 的安全防护 WAF 规则才会出…

Ray Tracing in one Weekend But on CUDA

Ray Tracing in one Weekend But on CUDA 环境说明项目代码项目内容思路实现方法效果 环境说明 代码运行在Visual Studio 2019环境&#xff0c;显卡为NVIDIA GeForce GTX 1650&#xff0c;CUDA版本为11.6&#xff0c;cuDNN版本为8.4.0。具体配置方式见CUDA C/C 从入门到入土 第…

洛谷P2370yyy2015c01 的 U 盘

传送门——P2370 yyy2015c01 的 U 盘 题解&#xff1a;题目意思很好理解&#xff0c;就是说&#xff0c;当能够达到预期的U盘的最小接口&#xff08;接口越大&#xff0c;能传递的文件越大&#xff09;&#xff0c;然后我们就需要先看题目了&#xff0c;有n个文件&#xff0c;每…

【数据结构(邓俊辉)学习笔记】图02——搜索

文章目录 0. 概述1. 广度优先搜索1.1 策略1.2 实现1.3 可能情况1.4 实例1.5 多联通1.6 复杂度1.7 最短路径 2. 深度优先搜索2.1 算法2.2 框架2.3 细节2.4 无向边2.5 有向边2.6 多可达域2.7 嵌套引理 3 遍历算法的应用 0. 概述 此前已经介绍过图的基本概念以及它在计算机中的表…

vector实现后半部分

一.迭代器失效 1.定义 指原迭代器在扩容/缩容/修改后指向无效元素或无效地址处 erase的迭代器失效 2.原因&#xff1a; 1.有的编译器实现erase会缩容拷贝 2.删除最后一个后&#xff0c;其指向无效元素 VS中不允许再次使用erase完的迭代器&#xff0c;为了让编写的代码移植…

Spring系列-SpringMvc父子容器启动原理解析

1、Spring整合SpringMVC 特性&#xff1a; 说到Spring整合SpringMVC唯一的体现就是父子容器&#xff1a; 通常我们会设置父容器&#xff08;Spring&#xff09;管理Service、Dao层的Bean, 子容器(SpringMVC)管理Controller的Bean .子容器可以访问父容器的Bean, 父容器无法访…

LLM——深入探索 ChatGPT在代码解释方面的应用研究

1.概述 OpenAI在自然语言处理&#xff08;NLP&#xff09;的征途上取得了令人瞩目的进展&#xff0c;这一切得益于大型语言模型&#xff08;LLM&#xff09;的诞生与成长。这些先进的模型不仅是技术创新的典范&#xff0c;更是驱动着如GitHub Copilot编程助手和Bing搜索引擎等广…

搭建大型分布式服务(三十九)SpringBoot 整合多个kafka数据源-支持Aware模式

系列文章目录 文章目录 系列文章目录前言一、本文要点二、开发环境三、原项目四、修改项目五、测试一下五、小结 前言 本插件稳定运行上百个kafka项目&#xff0c;每天处理上亿级的数据的精简小插件&#xff0c;快速上手。 <dependency><groupId>io.github.vipjo…

计算一个3x3矩阵对角线和其它两条线的元素之和

计算一个3x3矩阵对角线和其它两条线的元素之和 #include <stdio.h> int main () { int d0,b0,s,i,j; int a[3][3]{1,2,3,4,5,6,7,8,9}; for(i0,j2;i<3;i,j--) dda[i][i]a[i][j]; for(i0,j0;i<3;) {bba[i][j]a[i][j2]; ii2;} sdb; printf("d%d\nb%d\ns%d\n&qu…

5.25.12 数字组织病理学的自我监督对比学习

无监督学习可以弥补标记数据集的稀缺性。 无监督学习的一个有前途的子类是自监督学习&#xff0c;其目的是使用原始输入作为学习信号来学习显著特征。在这项工作中&#xff0c;我们解决了在没有任何监督的情况下学习领域特定特征的问题&#xff0c;以提高数字组织病理学界感兴…

R语言探索与分析-美国房价及其影响因素分析

一、选题背景 以多元线性回归统计模型为基础&#xff0c;用R语言对美国部分地区房价数据进行建模预测&#xff0c;进而探究提高多元回 归线性模型精度的方法。先对数据进行探索性预处理&#xff0c;随后设置虚拟变量并建模得出预测结果&#xff0c;再使用方差膨胀因子对 多重共…

使用Landsat的NDVI和NDWI阈值法土地分类

目录 分类效果源代码分类效果 创建一个包含多个层的影像合成:水体(NDWI > 0.5),植被(NDVI > 0.2),阴影区域的裸地(bare2但不包括bare1),和其他裸地(bare1)。然后,使用mosaic()方法合并这些层,并用clip(hh)方法裁剪到研究区域的范围。 源代码 var hh = ee.…

基于Java的零食管理系统的设计与实现(论文+源码)_kaic

摘 要 随着科技的进步&#xff0c;以及网络的普及&#xff0c;都为人们的生活提供了极大的方便。因此&#xff0c;在管理”三姆”宿舍在线零食商店时&#xff0c;与现代的网络联系起来是非常必要的&#xff0c;本次设计的系统在研发过程中应用到了Java技术&#xff0c;这在一定…

第一人称射击游戏:反恐精英(CS1.6) 支持win版和mac版下载

枪战老玩家还记得这款史诗巨作吗&#xff1f;Macz为广大游戏玩家倾情推出反恐精英(CS1.6) for Mac&#xff0c;CS1.6官方下载是由著名游戏《半条命》的其中一个游戏模组(MOD)衍生而成的游戏。逼真的画面&#xff0c;震撼的音效&#xff0c;3D的视角&#xff0c;多样的操作融合而…

LeetCode - 贪心(Greedy)算法集合(Python)[分配问题|区间问题]

欢迎关注我的CSDN&#xff1a;https://spike.blog.csdn.net/ 本文地址&#xff1a;https://spike.blog.csdn.net/article/details/139242199 贪心算法&#xff0c;是在每一步选择中&#xff0c;都采取当前状态下&#xff0c;最好或最优&#xff08;即最有利&#xff09;的选择&…