【C++】C++入门详解 I【C++入门 这一篇文章就够了】

news2024/11/20 12:25:25

C++入门

  • 前言
  • 一、C++关键字(C++98)
  • 二、命名空间 namespace
    • (一)namespace的出现
    • (二)namespace的定义
      • (1)namespace 的正常定义
      • (2)namespace的功能特性
        • 1. 命名空间 可嵌套
        • 2. 同一工程中允许存在多个相同名称的命名空间,编译器最后会合成同一个命名空间中。
    • 命名空间的使用
      • (1)加 命名空间名称 及 `::` 作用域限定符 [ 每次指定命名空间 ]
      • ☆(2) using 将 命名空间中某个成员 引入 [ 部分展开 ]
      • (3) using namespace 命名空间名称 引入 [ 全展开 ]
  • 三、using namespace std
  • 四、C++ 输入&输出 [ IO流 ]
    • (一)代码实现
      • (1)包含头文件 `# include<iostream>`
      • (2)cout cin endl
      • (3)<< _ 流插入运算符,>> _ 流提取运算符
    • (二)C++输入输出 的特性:可 自动识别变量类型
    • (三)cout,cin更复杂的用法
    • (三).h 头文件 以及 std命名空间
  • 五、缺省参数
    • (一) 缺省参数 概念
    • (二) 缺省参数分类
  • 六、函数重载
    • (一) 函数重载概念
    • (二)函数重载
      • (1)参数类型不同
      • (2)参数个数不同
      • (3)参数类型顺序不同
  • (三)函数重载 底层原理_名字修饰(name Mangling)



前言

C++ 就是在对 C语言使用中遇到的缺陷与不足的改进。

C++是在C的基础之上,容纳进去了面向对象编程思想,并增加了许多有用的库,以及编程范式等。熟悉C语言之后,对C++学习有一定的帮助。

本章节主要目标:

  1. 补充C语言语法的不足,以及C++是如何对C语言设计不合理的地方进行优化的,比如:作用域方面、IO方面、函数方面、指针方面、宏方面等。

  2. 为后续类和对象学习打基础


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

C++总计63个关键字(涵盖 C语言32个关键字)

在这里插入图片描述


二、命名空间 namespace

(一)namespace的出现

在C/C++中出现的问题:

  1. 变量、函数和后面要学到的类都是大量存在的,这些变量、函数和类的名称将都存在于全局作用域中,可能会导致很多冲突
  2. 写的变量名与库里面的名冲突
  3. 在项目异步进行时,最终项目合并时,也容易导致很多命名上的冲突(重命名)

如下面这个例子

#include <stdio.h>

#include <stdlib.h>        //包含rand()函数
int rand = 10;             //全局变量中也有 命名为rand的变量

// C语言没办法解决类似这样的命名冲突问题,所以C++提出了namespace来解决
int main()
{
 printf("%d\n", rand);
return 0;
}
// 编译后后报错:error C2365: “rand”: 重定义;以前的定义是“函数”
  • C++ namespace [ 关键字 ] 对此进行了优化:
    平时程序运行中 默认访问全局变量里的变量namespace相当于一堵围墙平时都会绕开,默认不会进入墙里找域访问 。只有 展开命名空间,才有权限进入命名空间内访问存放的变量。

使用 namespace 后

#include <stdio.h>

#include <stdlib.h>        //包含rand()函数

namespace nini{
int rand = 10;             
}
// C语言没办法解决类似这样的命名冲突问题,所以C++提出了namespace来解决
int main()
{
 printf("%d\n",nini::rand);   // :: 域作用限定符 
return 0;
}

使用命名空间的目的是对标识符的名称进行本地化,以避免命名冲突或名字污染
namespace 关键字的出现就是针对这种问题的。



(二)namespace的定义

(1)namespace 的正常定义

namespace[关键字] + 命名空间的名字 + { } +( { } 里面 )命名空间的成员

  1. 一般开发中是用 项目名字命名空间名
  2. 命名空间中可以定义 变量 / 函数 / 类型(如结构体等)

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

namespace nini
{
 // 命名空间中可以定义变量/函数/类型
 int rand = 10;                        //变量
 
 int Add(int left, int right)          //函数
 {
 return left + right;
 }

struct Node                            //类型
 {
 struct Node* next;
 int val;
 };
 
}


(2)namespace的功能特性

1. 命名空间 可嵌套
// 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;
     }
 }
 
}
2. 同一工程中允许存在多个相同名称的命名空间,编译器最后会合成同一个命名空间中。

ps:一个工程中的test.h和上面test.cpp中两个N1会被合并成一个

// test.h
namespace N1
{
int Mul(int left, int right)
 {
     return left * right;
 }
}


命名空间的使用

(1)加 命名空间名称 及 :: 作用域限定符 [ 每次指定命名空间 ]

int main()
{
    printf("%d\n", N::a);    // :: 作用域限定符 【指定命名空间】
    return 0;    
}

☆(2) using 将 命名空间中某个成员 引入 [ 部分展开 ]

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

(3) using namespace 命名空间名称 引入 [ 全展开 ]

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

  • 关于 全展开部分展开 的讨论:
    对命名空间进行展开 [ 命名空间全展开 ] (3) 其实是一件很危险的事,直接展开,全部暴露,又有冲突的风险。 而 每次指定命名空间(1)又很不方便 。
    指定展开(2)就可以解决问题 。指定展开 常用的
using std::cout;
using std::endl;

int main(){
cout<<"hello world\n";

int a=10;
double b=11.11;

cout << a << endl << b << endl;
cout << a << endl << b << endl;
cout << a << endl << b << endl;
}


三、using namespace std

std命名空间的使用惯例:

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

  1. 在日常练习中,建议直接 using namespace std 即可,这样就很方便。

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



四、C++ 输入&输出 [ IO流 ]

(一)代码实现

(1)包含头文件 # include<iostream>

  1. io _ int & out 的缩写 + stream 流 => iostream 输入输出流

后面使用cout,cin时,必须 包含< iostream >头文件 以及 按命名空间使用方法使用std
如下图


(2)cout cin endl

c(console 控制台)out,cin

  • cout 标准输出对象(控制台) [ linux 叫其 终端 ]
    在这里插入图片描述

  • cin 标准输入对象(键盘)

cout和cin是全局的流对象。

  • endl [ endline 结束这一行 ] 是特殊的C++符号(C++换行符),表示换行输出

他们都包含在< iostream >头文件中。


(3)<< _ 流插入运算符,>> _ 流提取运算符


实际上 cout和cin分别是ostream和istream类型的对象>>和<<也涉及运算符重载等知识
这些知识我们我们后续才会学习,所以我们这里只是简单学习他们的使用。后面我们还有有一个章节更深入的学习IO流用法及原理


(二)C++输入输出 的特性:可 自动识别变量类型

使用C++输入输出更方便,不需要像printf/scanf输入输出时那样,需要手动控制格式
C++的输入输出可以自动识别变量类型

#include <iostream>
using namespace std;

int main()
{    
   //IO流
   // 可以自动识别变量的类型
   // << 流插入
   std::cout << "hello world";
   int a = 10;
   double b = 11.11;
   
            //int //字符串 //double //字符
   std::cout << a << "\n"<< b << '\n';
   std::cout << a << std::endl << b << std::endl;
   
   return 0;
}


(三)cout,cin更复杂的用法

关于cout和cin还有很多更复杂的用法,比如控制浮点数输出精度控制整形输出进制格式等等。

因为C++兼容C语言的用法所以,这种在C++的复杂用法,可以在C中用其基本语法来实现

int main(){
cout << "hello world\n";

int a = 10;
double b = 11.11;

cout << a << endl << b << endl;
printf("%.1lf\n",b);      //C++兼容C语言的用法,这种在C++的复杂用法,可以在C中用其基本语法来实现
}

这些又用得不是很多,我们这里就不展开学习了。后续如果有需要,我们再配合文档学习。


(三).h 头文件 以及 std命名空间

注意:早期标准库将所有功能 在全局域中实现声明在.h后缀的头文件中使用时只需包含对应头文件即可。

后来将其实现在std命名空间下,为了和C头文件区分,也为了正确使用命名空间规定C++头文件不带.h;旧编译器(vc 6.0)中还支持<iostream.h>格式,后续编译器已不支持,因此推荐使用 <iostream.h> + std 的方式。



五、缺省参数

(一) 缺省参数 概念

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

void Func(int a = 0)
{
 cout<<a<<endl;
}
int main()
{
 Func();     // 没有传参时,使用参数的默认值
 Func(10);   // 传参时,使用指定的实参
return 0;
}


(二) 缺省参数分类

  • 全缺省参数
void Func(int a = 10, int b = 20, int c = 30)
 {
     cout<<"a = "<<a<<endl;
     cout<<"b = "<<b<<endl;
     cout<<"c = "<<c<<endl;
 }
  • 半缺省参数
    半缺省参数必须 从右往左 依次来给出,不能间隔着给
void Func(int a, int b = 10, int c = 20)
 {
     cout<<"a = "<<a<<endl;
     cout<<"b = "<<b<<endl;
     cout<<"c = "<<c<<endl;
 }

注意:

  1. 缺省参数不能在 函数声明 和 定义 中同时出现
    如果 声明与定义位置同时出现 ,恰巧两个位置提供的值不同,那编译器就无法确定到底该用那个缺省值。
//a.h
  void Func(int a = 10);
  
  // a.cpp
  void Func(int a = 20)
 {}
  1. 缺省值必须是 常量 或者 全局变量
  2. C语言不支持(编译器不支持)


六、函数重载

C不支持同名函数,C都是靠函数名来识别函数的,但功能类似,只是因为 形参列表 (参数个数 或 类型 或 类型顺序)不同 ,而因此要开辟很多不同的函数名。这是一件很麻烦且效率低下的事情。

对此,C++做出改进,提出了函数重载的概念。



(一) 函数重载概念

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

  • [ 返回值可用可不用 ]
    会出现不知道该调用谁。


(二)函数重载

(1)参数类型不同

#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;
}

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

(2)参数个数不同

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

int main()
{ 
 f();//f()则不知道该调用 f()还是f(int a)  
 f(10);     //f(10)可以很明确的是传给f(int a);
}

(3)参数类型顺序不同

// 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()
{
 f(10, 'a');
 f('a', 10);
 return 0;

}


(三)函数重载 底层原理_名字修饰(name Mangling)

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

在C/C++中,一个程序要运行起来,需要经历以下几个阶段:预处理编译汇编链接
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

  1. 预处理(.i 文件)
    预处理指令,头文件展开


  1. 编译(.s 文件)
    语法分析,词法分析,语义分析,符号汇总

(语法束)检查语法,生成汇编代码 [指令级代码]( 给我们看的 )


2.1 函数调用在编译阶段,call(地址)
[ 只有声明 ( 但编译器让它过 ),没有地址 ]
[会 在链接阶段,通过根据汇编阶段生成的.o文件符号表( 找到对应函数名的地址 )将call()里面的地址进行链接 ]
在这里插入图片描述


2.2 并且将参数带入进行修饰产生 [ 函数名修饰规则 ]
由于Windows下vs的修饰规则过于复杂,而Linux下g++的修饰规则简单易懂,下面我们使用了g++演示了这个修饰后的名字。

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

  • 采用C语言编译器编译后结果
    在这里插入图片描述
    结论:在linux下,采用gcc编译完成后,函数名字的修饰没有发生改变。

  • 采用C++编译器编译后结果
    在这里插入图片描述结论:在linux下,采用g++编译完成后,函数名字的修饰发生改变,编译器将函数参数类型信息添加到修改后的名字中。

  • Windows下名字修饰规则
    在这里插入图片描述

对比Linux会发现,windows下vs编译器对函数名字修饰规则相对复杂难懂,但道理都是类似的,我们就不做细致的研究了

【扩展学习:C/C++函数调用约定和名字修饰规则–有兴趣好奇的同学可以看看,里面有对vs下函数名修饰规则讲解】
C/C++ 函数调用约定

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

如果两个函数 函数名和参数是一样 的,返回值不同不构成重载 的,因为调用时编译器没办法区分
返回值可用可不用 ,会出现不知道该调用谁的情况。



  1. 汇编( 可重定位目标文件 .o 文件)
    3.1 形成符号表。(汇编调用函数时,才会call 地址 ,因此符号表就是在这时产生的)

    符号表:
    形式 “ 函数名 地址 ” [ 函数名 和 地址 的映射 ]
    在这里插入图片描述
    3.2 汇编指令 -> 二进制指令 [ 转换成二进制的机器码( CPU 能认识的 )] -> test.o



  1. 链接
    合并段表
    符号表的合并 和 符号表的重定位
    合并到一起,链接一些没有确定的函数地址等 [ 用函数名去找地址( 函数名修饰规则 )]

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

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

那么链接时,面对Add函数,链接接器会使用哪个名字去找呢?这里就通过我们前面 编译阶段讲的 每个编译器都有自己的 函数名修饰规则来找。

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

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

相关文章

Android系统开发快速寻找代码(如何在文件夹中寻找代码)

很多时候对于Android系统开发小白而言&#xff0c;例如预置APK&#xff0c;知道了APK包名不知道具体代码位置需要去寻找代码&#xff0c;但是Android系统代码十分庞大&#xff0c;如何快速准确查询代码是个问题。 本人目前只探索到了一些方法&#xff0c;如有更有效的办法可以…

github私有仓库开发,公开仓库发布版本

文章目录 github私有仓库开发,公开仓库发布版本需求背景实现思路GitHub Releases具体步骤广告 github私有仓库开发,公开仓库发布版本 需求背景 github私有仓库开发,公开仓库发布版本&#xff0c;既可以保护源代码,又可以发布版本给用户使用。许多知名软件项目都采用了这样的开…

VS Code画流程图:draw.io插件

文章目录 简介快捷键 简介 Draw.io是著名的流程图绘制软件&#xff0c;开源免费&#xff0c;对标Visio&#xff0c;用过的都说好。而且除了提供常规的桌面软件之外&#xff0c;直接访问draw.io就可以在线使用&#xff0c;堪称百分之百跨平台&#xff0c;便捷性直接拉满。 那么…

3.HTML中语法规范

3. HTML语法规范 3.1 基本语法概述 3.1.1 HTML标签 1 HTML 标签是由尖括号包围的关键字&#xff0c;例如<html>。 2. HTML 标签通常是成对出现的&#xff0c;例如<html>和</html>,我们称为双标签。标签对中的第一个标签是开始标签&#xff0c;第二个标签是…

Windows10腾讯文档下载和安装

文章目录 Windows10腾讯文档下载和安装官网下载执行安装 Windows10腾讯文档下载和安装 官网下载 官网 下载后&#xff1a; 执行安装 找到下载目录 安装后打开 扫描登录即可

2023亚太杯数学建模A题B题C题思路代码分析

文章目录 0 赛题思路1 竞赛信息2 竞赛时间3 建模常见问题类型3.1 分类问题3.2 优化问题3.3 预测问题3.4 评价问题 4 建模资料5 最后 0 赛题思路 &#xff08;赛题出来以后第一时间在CSDN分享&#xff09; https://blog.csdn.net/dc_sinor?typeblog 1 竞赛信息 2023年第十三…

gma 2.0.3 (2023.11.12) 更新日志

安装 gma 2.0.3 pip install gma2.0.3新增 此版本为 gma 2 功能更新最大的版本&#xff0c;且主要集中在矢量数据处理上。 0.1 io.ReadVector&#xff1a;直接打开矢量数据为Layer&#xff0c;用以简化io.Open.GetLayer 过程。Layer的新增功能如下&#xff1a; 序号功能性质说…

redis的基本命令,并用netty操作redis(不使用springboot或者spring框架)就单纯的用netty搞。

大家如果对使用netty搞这些http请求什么的感兴趣的&#xff0c;可以参观我自己创建的这个项目。 nanshaws/nettyWeb: 复习一下netty&#xff0c;并打算做一个web项目出来 (github.com) Redis的基本命令包括&#xff1a; SET key value&#xff1a;设置指定key的值。 GET key…

搭建产品帮助中心其实很简单,方法都在这了!

网站帮助中心是一个为用户提供支持和解答问题的重要资源。它不仅可以提高用户体验&#xff0c;还能减少用户问题反馈的数量。通过提供清晰、易于理解的文档和指南&#xff0c;帮助中心可以帮助用户更好地了解产品或服务&#xff0c;并解决他们在使用过程中遇到的问题。接下来我…

2023亚太杯数学建模B题思路

文章目录 0 赛题思路1 竞赛信息2 竞赛时间3 建模常见问题类型3.1 分类问题3.2 优化问题3.3 预测问题3.4 评价问题 4 建模资料5 最后 0 赛题思路 &#xff08;赛题出来以后第一时间在CSDN分享&#xff09; https://blog.csdn.net/dc_sinor?typeblog 1 竞赛信息 2023年第十三…

matlab 二自由度操纵稳定性汽车模型

1、内容简介 略 19-可以交流、咨询、答疑 二自由度操纵稳定性汽车模型 二自由度、操纵稳定性、操纵动力学 2、内容说明 1 模型假设 忽略转向系的影响&#xff0c;以前、后轮转角作为输入&#xff1b;汽车只进行平行于地面的平面运动&#xff0c;而忽略悬架的作用&#xf…

Halcon WPF 开发学习笔记:HSmartWindowControlWPF正常加载

文章目录 加载问题相关文章彻底解决 加载问题 我们在WPF中使用Halcon的时候&#xff0c;会出现图片被拉伸的问题&#xff0c;需要拖动才可以解决&#xff0c;我网上找了好久&#xff0c;终于找到了如何成功解决这个问题。 相关文章 3.7 Halcon 窗体显示对象消失问题 【halcon】…

(二)七种元启发算法(DBO、LO、SWO、COA、LSO、KOA、GRO)求解无人机路径规划MATLAB

一、七种算法&#xff08;DBO、LO、SWO、COA、LSO、KOA、GRO&#xff09;简介 1、蜣螂优化算法DBO 蜣螂优化算法&#xff08;Dung beetle optimizer&#xff0c;DBO&#xff09;由Jiankai Xue和Bo Shen于2022年提出&#xff0c;该算法主要受蜣螂的滚球、跳舞、觅食、偷窃和繁…

手撕数据库连接池

1.有开源的数据库连接池&#xff0c;你为啥不用&#xff1f; 这个不是因为闲的没事干&#xff0c;先说下需求背景 我们有一个数据源管理模块&#xff0c;配置的数据源连接&#xff0c;用户名&#xff0c;密码等信息 在数据源管理模块配置好之后&#xff0c;去另一个模块选择数…

日语形容词分类

变成肯定形式很简单&#xff0c;就是在后面加个です就可以了&#xff0c;不列在表格了 一类形容词 汉字い并且是以い结尾的形容词 否定形式是去掉い然后在后面加上くないです 更加正式的否定是去掉い然后加上くありません 日文平假名过去式过去否定中文熱いあつい熱くないで…

[护网杯 2018]easy_tornado 1(两种解法!)

题目环境&#xff1a;发现有三个txt文本文件 /flag.txt/welcome.txt/hints.txt 依此点开 flag在/fllllllllllllag文件中 在hints.txt文件中发现md5计算 md5(cookie_secretmd5(filename)) 并且三个文件中都存在filehash&#xff08;文件名被哈希算法加密32位小写&#xff09; 猜…

Halcon WPF 开发学习笔记(2):Halcon导出c#脚本和WPF初步开发

文章目录 前言HalconC#教学简单说明如何二开机器视觉如何二次开发Halcon导出Halcon脚本新建WPF项目&#xff0c;导入Halcon脚本和Halcon命名空间 前言 我目前搜了一下我了解的机器视觉软件&#xff0c;有如下特点 优点缺点兼容性教学视频(B站前三播放量)OpenCV开源&#xff0…

如何让VirtualBox系统使用Ubuntu主机的USB

如何让VirtualBox系统使用Ubuntu主机的USB 当通过 VirtualBox 尝试不同的操作系统时&#xff0c;访问虚拟机中的 USB 驱动器来传输数据非常有用。 安装Guest Additions 自行百度安装Guest Additions的方法&#xff0c;最终的效果如下&#xff1a; 将用户添加到 vboxusers 组…

4.HTML网页开发的工具

4. 网页开发的工具 4.1 快捷键 4.1.1 快速复制一行 快捷键&#xff1a;shiftalt下箭头&#xff08;上箭头&#xff09; 或者ctrlc 然后 ctrlv 4.1.2 选定多个相同的单词 快捷键&#xff1a; ctrld 4.1.3 添加多个光标 快捷键&#xff1a;ctrlalt上箭头&#xff08;下箭头&…

企业云盘与个人云盘:区别与特点一览

企业云盘是企业在寻找文件协同工具的过程中绕不开的一个选项。企业为什么需要专门购置企业网盘&#xff0c;个人云盘能否满足企业的文件协作需求呢&#xff1f;企业云盘和个人云盘有什么区别呢&#xff1f; 企业云盘与个人云盘的区别 1、使用对象&#xff1a;顾名思义&#xf…