news 2026/10/22 1:14:40

【C++进阶之路】初始C++语法(上)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【C++进阶之路】初始C++语法(上)

文章目录

  • 前言
  • 一.命名空间
    • 命名冲突
    • 命名空间的使用
      • 展开命名空间
      • 作用域限定符访问
        • 作用域
    • 命名空间的合并
    • 命名空间的嵌套
  • 二.输入输出
    • 打印
      • 流插入运算符
    • 输入
      • 流提取运算符
  • 三.缺省参数
    • 全缺省
    • 半缺省
    • 跨文件缺省函数参数
    • 缺省参数的使用格式
  • 四.函数重载
    • 参数个数不同
    • 参数类型不同
    • 参数顺序不同
    • 注意事项
      • 返回类型不能当做函数重载
      • 参数名不能被当做函数重载
      • 相同类型的缺省参数不是函数重载
    • LInux下的重载函数的符号化

前言

  • 因为C++兼容C的大多数语法,所以我们用C逐步讲解,之后再换成C++语法

一.命名空间

  • 基本概念 :namespace +空间名+{}
  • 切记,最后可没有 ;

命名冲突

#include<stdio.h>#include<stdlib.h>intrand=0;intmain(){printf("%d",rand);return0;}

编译时,我们会看到:

  • 结论:与头文件stdlib.h的rand函数的命名冲突了

  • 问题:不改变此变量的名字的前提下,如何正确打印此变量?

  • 答案: 使用命名空间将变量进行封装

注意:命名空间的名字也会发生命名冲突,因此不要起rand!

#include<stdio.h>#include<stdlib.h>namespace shunhua{intrand=0;}intmain(){printf("%d",rand);return0;}
  • 这样就对了吗?
  • 其实不对。

这里其实识别的是rand函数,不是命名空间里的变量!

  • 因此:命名空间是将变量或者函数封装,因此是无法直接访问的!

命名空间的使用

展开命名空间

  • using namespace + 空间名+ ;
    接着上文
#include<stdio.h>#include<stdlib.h>namespace shunhua{intrand=0;}using namespace shunhua;intmain(){printf("%d",rand);return0;}

再次编译,看结果

  • 这是怎么回事呢?
  • 答案 :使用命名空间,相当于将命名空间暴露与全局范围中,因此又回到了我们要最初要解决的问题。
    • 命名冲突打印指定变量
  • 接着往下讨论

作用域限定符访问

作用域

学过C语言,想必都能看懂这一段代码。

#include<stdio.h>intrand=1;intmain(){intrand=0;printf("%d\n",rand);return0;}
  • 全局变量与局部变量同名时,优先使用局部变量。
  • 换到C++,域是查找变量的默认优先顺序:
  • 1.局部域
  • 2.全局域
  • 3.命名空间访问变量用——展开的命名空间/限定符访问。

作用域限定符:

: :前面要不加默认使用全局变量,前面加命名空间使用的是命名空间的变量
像这样

  1. :+变量——就用的是全局变量
  2. 作用域:+变量——就用的是指定的域的变量
#include<stdio.h>namespace shun_hua{intrand=3;}intrand=1;intmain(){intrand=0;printf("%d\n",rand);//局部变量中查找printf("%d\n",::rand);//全局域里面查找printf("%d\n",shun_hua::rand);//在命名空间里面查找return0;}

执行结果:

回头解决要解决的问题:

#include<stdio.h>#include<stdlib.h>namespace shunhua{intrand=0;}intmain(){printf("%d",shunhua::rand);return0;}

此时再编译没问题,执行一下:

成功打印出命名空间的值

  • 命名冲突打印指定变量

命名空间的合并

  • 当我们多次定义同名空间时,相当于定义了一个命名空间,同名的命名会自动将变量与函数进行合并,而不是我们想的重命名!
#include<stdio.h>#include<stdlib.h>namespace shun_hua{intrand=0;inty=1;}namespace shun_hua{intx=2;intz=3;}intmain(){printf("%d\n",shun_hua::rand);printf("%d\n",shun_hua::x);printf("%d\n",shun_hua::y);printf("%d\n",shun_hua::z);return0;}
  • 这里面的命名空间在合并时,是不允许出现相同的函数或变量出现两次的,如果有会直接在语法上,报错。也就是说命名空间的合并是在编译阶段完成的!
  • 如果需要在一个命名空间里面出现两个相同变量怎么办呢?
  • 命名空间的嵌套

命名空间的嵌套

  • 1.命名空间的嵌套是可以使用相同名字的。
  • 2.这样展开命名空间编译器会不知道展开哪个,从而报错
#include<stdio.h>namespace shun_hua{intx=0;namespace shun_hua{intx=1;}}//using namespace shun_hua;intmain(){printf("%d\n",shun_hua::shun_hua::x);return0;}

输出结果:

二.输入输出

我们首先要明白C++库的基本结构

  • 因此C++库是被封装在std命名空间里面的,使用C++库里的对象得通过std访问。
  • C++包含头文件是不需要后缀.h
  • 输入输出文件在iostream的头文件中

拓展: 早期的头文件在全局域中实现,因此头文件含.h, 后来为了与C头文件区分以及正确的使用命名空间,声明C++的头文件不带.h,因此我们现在看到的iostream不带头文件,而在早期的VC6.0版本还可以使用iostream.h的版本。

打印

流插入运算符

<<跟C语言的左移操作符意义不同,这里是流插入运算符,将数据流入输出流。

打印hello world

#include<iostream>//包含头文件using namespace std;//使用命名空间,这两者缺一不可intmain(){cout<<"hello world\n";return0;}

我们一般看到的写法是这样的

#include<iostream>//包含头文件using namespace std;//使用命名空间,这两者缺一不可intmain(){cout<<"hello world"<<endl;//这里的endl其实就是"\n"return0;}
  • 我们不推荐这样使用命名空间,因为这样将std的命名空间暴露在全局域中,失去了命名空间创建的意义。
    一般推荐这样写
#include<iostream>//包含头文件usingstd::cout;usingstd::endl;//这其实是我们使用命名空间的符号的声明intmain(){cout<<"hello world"<<endl;std::cout<<"hello world"<<std::endl;//在使用时也可以这样写,不过在重复多次写这里语句时,比较麻烦。return0;}

输入

流提取运算符

  • > >与C语言的右移操作符不同,这里是流提取,将数据输进输入流

输入一个整形,并将这个整形打印

#include<iostream>using std::cin;using std::cout;using std::endl;intmain(){intx=0;cin>>x;//这是将输入流的数据读取出来放进xcout<<x<<endl;return0;}
  • 总结:cout和cin会自动识别类型,不像printf和scanf需要手动的控制其类型,因此还是比较方便的。

特殊的,对于字符指针,不会将地址进行打印,而会打印对应的字符串。

三.缺省参数

  • 缺省参数,是声明或定义函数时为函数的参数指定一个默认值。在调用该函数时,如果没有指定实参则采用该默认值,否则使用指定的实参。
  • 也就是说在函数的指定参数有默认值的情况下,调用函数时,指定参数可以传参,也可不传,即为缺省。

全缺省

  • 函数的定义或者声明时,函数的参数都有默认值
#include<iostream>using std::cout;using std::endl;intadd(intx=0,inty=0){returnx+y;}intmain(){cout<<add()<<endl;cout<<add(1,2)<<endl;cout<<add(1)<<endl;//cout<<add(,2)<<endl;//语法规定不行return0;}
  • 函数缺省,调用时,从左往右进行传参,且从左往右是与函数的参数一 一对应,不能省略的。

半缺省

  • 半缺省指的是一部分参数缺省,缺省参数只能从右往左进行缺省
  • 注意:可不是一半的参数缺省
  • 缺省顺序:只能从右向左进行缺省,而不能从左向右进行缺省。这是因为函数在传参时从左向右进行传参的。
#include<iostream>using std::cout;using std::endl;intadd(intx,inty=0){returnx+y;}intmain(){cout<<add(1)<<endl;cout<<add(1,2)<<endl;return0;}
  • 用途:在单链表初始化时,可以指定开辟大小,也可以指定默认参数。

跨文件缺省函数参数


add.h文件

intadd(intx=0,inty=0);

add.cpp文件

#include"add.h"intadd(intx,inty){returnx+y;}

test.cpp文件

#include"add.h"#include<iostream>using std::cout;using std::endl;intmain(){cout<<add(1)<<endl;cout<<add(1,2)<<endl;return0;}
  • 情况:缺省参数的函数定义与声明在不同文件中
  • 在函数声明中需声明缺省参数,定义则不用写缺省参数,否则会出现重定义。
  • 原因:头文件的函数声明,在编译期间就会被识别,相当于先给编译器一个承诺,函数是什么样子的,而函数定义是在链接期间被检查的,因此声明时前提(承诺),定义是结果(无需写缺省参数)。

缺省参数的使用格式

  • 缺省参数只能用常量或者具有全局属性的变量
#include<iostream>usingstd::cout;usingstd::endl;#defineMAX100//常量intx=0;//全局变量intadd(intmax=MAX,intmin=x){returnmax+min;}intmain(){cout<<add()<<endl;return0;}

四.函数重载

  • 重载,顾名思义就是一词多义,比如比如:以前有一个笑话,国有两个体育项目大家根本不用看,也不用担心。一个是乒乓球,一个是男足。前者是“谁也赢不了(乒乓)!”,后者是“(国足)谁也赢不了!”。

  • 函数重载就是函数同名不同义。

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

参数个数不同

#include<iostream>using std::cout;using std::endl;intadd(){return0;}intadd(intx){returnx;}intmain(){cout<<add()<<endl;cout<<add(1)<<endl;}

参数类型不同

#include<iostream>using std::cout;using std::endl;intadd(intx,inty){return0;}intadd(doublex,doubley){return0;}intmain(){cout<<add(1,1)<<endl;cout<<add(1.0,1.0)<<endl;}

参数顺序不同

#include<iostream>using std::cout;using std::endl;intadd(intx,doubley){return0;}intadd(doubley,intx){return0;}intmain(){cout<<add(1,1.0)<<endl;cout<<add(1.0,1)<<endl;}

注意事项

返回类型不能当做函数重载

  • 函数重载是指的函数调用,所发生的类型识别和参数个数,从而确定调用哪个同名函数,而函数的返回值是不能根据函数调用进行确定的

示例:

  • 首先说明此代码会报错,原因是在函数调用时,不能区分返回类型,因此调用存在歧义。
#include<iostream>usingstd::cout;usingstd::endl;intadd(intx,inty){return0;}floatadd(intx,inty){return0;}intmain(){cout<<add(1,0)<<endl;cout<<add(1,1)<<endl;}

编译结果:

参数名不能被当做函数重载

#include<iostream>usingstd::cout;usingstd::endl;intadd(intx,inty){return0;}intadd(inty,intx){return0;}

编译结果:

相同类型的缺省参数不是函数重载

示例:

#include<iostream>using std::cout;using std::endl;intadd(intx,inty=0){return0;}intadd(intx,inty){return0;}

编译结果:

error: redefinition of 'int add(int, int)',即为重定义了函数、

LInux下的重载函数的符号化

Linux下gcc编译的结果

  • 结论:函数符号化为函数本身的名字
    Linux下g++编译的结果

  • g++编译的生成的函数符号名的规则:_Z+函数名长度+函数名+参数类型的首字母

  • 总结:C++本身其实不是通过函数名进行查找,而是通过函数符号化之后的结果,访问地址从而调用函数。

补充:关键字

  • export关键字,C++11废除了这个 export关键字的含义,但保留这个关键字,供以后使用。
    这个关键字是为了驯服模板声明与定义分离而设置的关键字,可惜功能太次被废掉了。
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/22 1:14:26

设计模式16——适配器

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/22 1:14:00

【Pytorch】Docker:Pytorch报错insufficient shared memory (shm)

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/22 1:13:51

多线程高并发编程(5) -- CountDownLatch、CyclicBarrier源码分析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/22 1:13:11

MySQL笔记(2)-- CURD多表操作、库表操作、约束条件、字段类型

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/22 1:12:27

基于PJ85718DM与STM32F745ZG的本地远程温度监测方案

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/22 1:12:23

手写编译器前端:从词法分析到三地址码的完整实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华