文章目录

  • (1)前言
  • (2)C++关键字(C++98)
  • (3)命名空间
    • 1)命名空间的定义
    • 2)命名空间的使用
  • (3)C++的输入&输出
  • (4)缺省参数
    • 1)缺省参数的概念
    • 2)缺省参数的分类
  • (5)函数重载(很重要)
  • (6)extern "c"

(1)前言

C++是C语言的继承,兼容绝大多数C的语法,在其基础上增加了一些语法,一般是为了解决C语言做不到的事情、修改不够好的地方

  • 什么是C++

C语言是结构化和模块化的语言,适合处理较小规模的程序。对于复杂的问题,规模较大的程序,需要高度的抽象和建模时,C语言则不合适。为了解决软件危机, 20世纪80年代, 计算机界提出了OOP(object oriented programming:面向对象思想),支持面向对象的程序设计语言应运而生。

1982年,Bjarne Stroustrup 博士在C语言的基础上引入并扩充了面向对象的概念,发明了一种新的程序言。为了表达该语言与C语言的渊源关系,命名C++。因此:C++是基于C语言而产生的,它既可以进行C语言的过程化程序设计,又可以进行以抽象数据类型为特点的基于对象的程序设计,还可以进行面向对象的程序设计。

  • C++的发展史
最重要的两个版本 内容
C++98 C++标准第一个版本,绝大多数编译器都支持,得到了国际标准化组织(ISO)和美国标准化协会认可,以模板方式重写C++标准库,引入了STL(标准模板库)
C++11 增加了许多特性,使得C++更像一种新语言,比如:正则表达式、基于范围for循环、auto关键字、新容器、列表初始化、标准线程库等
  • C++的应用领域
  1. 操作系统以及大型系统软件开发
  2. 服务器端开发
  3. 人工智能
  4. 网络工具
  5. 游戏开发
  6. 嵌入式领域
  7. 数字图像处理
  8. 分布式应用
  9. 移动设备
  • 学习C++:建议不要把「精通C++」作为一个一年目标,应该要把学习语言作为一个持续的过程,同时要把语言运用在具体的应用场合中。

(2)C++关键字(C++98)

  • C++共有63个关键字,其中有32个关键字是我们在学习C语言时就见过的
  • 在接下来的学习过程中,学到某个关键字时再展开细讲
asm do if return try continue
auto double inline short typedef for
bool dynamic_cast int signed typeid public
break else long sizeof typename throw
case enum mutable static union wchar_t
catch explicit namespace static_cast unsigned default
char export new struct using friend
class extern operator switch virtual register
const false private template void true
const_cast float protected this volatile while
delete goto reinterpret_cast

(3)命名空间

  • C语言中存在的一个问题

在不同的作用域,我们可以定义同名的变量;在同一作用域,不能定义同名的变量。

所以在一个大项目中,多个人分工写代码,最后合在一起时,你写的代码和我写的代码中的命名可能会冲突,我们写的代码中的命名又可能会和标准库里的冲突。

假如张三写了个函数取名为 Add,我也写了个函数,取名也为 Add,代码合在一起时,可能会引起命名冲突等等。

  • 举例说明

如果没有包含 stdlib.h 头文件,代码可以正常运行;

但包含之后,因为 stdlib.h 库中有一个叫 rand 函数,全局变量 rand 与其冲突了。

#include<stdio.h>
#include<stdlib.h> /*rand*/int rand = 10;  //全局变量randint main()
{printf("%d\n", rand);  //error: "rand"重定义,以前的定义是"函数"return 0;
}
  • C++提出了命名空间来解决命名冲突的问题

在C/C++中,变量、函数和类都是大量存在的,这些变量、函数和类的名称将都存在于全局作用域中,可能会导致很多冲突。使用命名空间的目的是对标识符的名称进行本地化,以避免命名冲突或名字污染,namespace 关键字的出现就是针对这种问题的。

命名空间相当于一个域,把各自写的东西隔起来。


1)命名空间的定义

  • 定义命名空间,需要使用到 namespace 关键字,后面跟命名空间的名字,然后接一对 { } 即可,{ } 中即为命名空间的成员。

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

  • 命名空间的普通定义
//命名空间的普通定义
namespace L1  //L1为命名空间的名称
{//命名空间中可以定义变量/函数/类型int a = 10;int Add(int x, int y){return x + y;}struct Node{struct Node* next;int val;};
}
  • 命名空间的嵌套定义
//命名空间的嵌套定义
namespace L2
{int a = 10;namespace L3  //嵌套定义一个名为L3的命名空间{int b = 20;int sub(int x, int y){return x - y;}}
}
  • 同一个工程中允许存在多个相同名称的命名空间,编译器最后会合成到同一个命名空间中(所以相同名称的命名空间中不能出现同名的变量/函数/类型,否则会引起冲突)

2)命名空间的使用

//定义一个命名空间N1
namespace N1
{int a = 10;int b = 10;int Add(int x, int y){return x + y;}
}

命名空间的使用有三种方式:

  • 全部展开到全局,就可以直接使用(使用 using namespace 将命名空间名称引入)
// 优点:用起来方便
// 缺点:把自己的定义暴露出去了,导致命名污染
//using namespace std;  //std是包含C++标准库的命名空间using namespace N1;
int main()
{Add(1, 2);return 0;
}
  • 访问命名空间中的成员时,加命名空间名称及作用域限定符
// 优点:不存在命名污染
// 缺点:用起来麻烦,每个都需要去指定命名空间int main()
{printf("%d\n", N1::a);N1::Add(1, 2);return 0;
}
  • 使用 using 将命名空间中常用的成员引入
// 优点:不会造成大面积的命名污染,又可以把常用的给展开
// 这是一个折中的解决方案using N1::Add;  //命名空间N1中Add函数和变量a用的非常多,将其展开到全局
using N1::a;int main()
{printf("%d\n", a);Add(1, 2);return 0;
}
  • 补充一点:命名空间 std 的规范使用

C++把标准库里面的东西都放到命名空间 std 中,所以在实际开发中,为了避免你自己写的变量/函数/类型等等与标准库中的冲突,建议不要把命名空间 std 直接展开到全局,而是把常用的展开就行,一般规范的写法为:

#include<iostream>
//using namespace std;  //不要将std直接展开到全局//把常用的展开就行
using std::cout;
using std::endl;int main()
{cout << "hello world" << endl;return 0;
}

如果是日常练习,就不需要像上面这么规范,直接展开用


(3)C++的输入&输出

C语言有自己的输入输出函数 scanf 和 printf,那么C++也有自己独特的输入输出方式,cin 标准输入流cout 标准输出流,必须包含 头文件和 std 标准库命名空间。

注意:早期标准库将所有功能在全局域中实现,声明在 .h 后缀的头文件中,使用时只需包含对应头文件即可,后来将其实现在 std 命名空间下,为了和 C 头文件区分,也为了正确使用命名空间,规定C++头文件不带.h;旧编译器(vc 6.0)中还支持 <iostream.h> 格式,后续编译器已不支持,因此推荐使用 + std 的方式。

使用C++输入输出更方便,它可以自动识别变量的类型,不需增加数据格式控制,比如:整形–%d,字符–%c

#include<iostream>
using namespace std;  //C++标准库int main()
{int a;cin >> a;  // >> 输入运算符/流提取运算符cout << a; // << 输出运算符/流插入运算符cout << endl;  //换行,等价于 cout << '\n';return 0;
}
  • 注意:C++中的浮点数,当小数点后数字超过 5 位时,cout 规定输出的是小数点后 5 位,如果想要实现浮点数的格式化输出,那就建议用 printf 来输出,使用一定要灵活变通。



(4)缺省参数

1)缺省参数的概念

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

#include<iostream>
using namespace std;void Func(int a = 0)
{cout << a << endl;
}int main()
{Func();   //没有传参时,使用参数的默认值Func(10); //传参时,使用指定的参数return 0;
}
  • 缺省参数的使用

以前入栈时必须得判断一下容量是否为0,若为0,给capacity赋一个初始值,但赋的这个初始值没办法灵活的去控制,有了缺省参数,我们就可以根据需要,来控制初始容量。

#include<iostream>
using namespace std;//定义一个顺序栈
struct Stack
{int* a;int top;int capacity;
};//初始化栈,给栈容量设置一个默认值4
void StackInit(struct Stack* ps, int DefaultCapacity = 4)
{ps->a = (int*)malloc(sizeof(int) * DefaultCapacity);ps->top = -1;ps->capacity = 0;
}//入栈
void StackPush(struct Stack* ps)
{if (ps->top == ps->capacity + 1){ps->capacity *= 2;//......}//......
}int main()
{//假如我明确知道这里至少要存100个数据到st1中去struct Stack st1;StackInit(&st1, 100);//假如我不知道要存多少个数据到st2中去struct Stack st2;StackInit(&st2);return 0;
}

2)缺省参数的分类

  • 全缺省参数
#include<iostream>
using namespace std;void Func(int a = 10, int b = 20, int c = 30)
{cout << a + b + c << endl;
}int main()
{//调用全缺省参数的函数方式很灵活Func();Func(1);Func(1, 2);Func(1, 2, 3);return 0;
}
  • 半缺省参数
#include<iostream>
using namespace std;void Func(int a, int b = 10, int c = 20)
{cout << a + b + c << endl;
}int main()
{//调用半缺省参数的函数Func(1);       //1传给aFunc(1, 2);    //1传给a,2传给bFunc(1, 2, 3); //1传给a,2传给b,3传给creturn 0;
}
  • 总结
  1. 半缺省参数必须从右往左依次来给出,不能间隔着给
  2. 缺省参数不能在函数声明和定义中同时出现(建议声明的时候给缺省参数,定义的时候就不要给了)
//注意:如果声明与定义位置同时出现,恰巧两个位置提供的值不同,那编译器就无法确定到底该用那个缺省值。//test.h
void Func(int a = 10);//test.c
void Func(int a = 20)
{//......
}
  1. 缺省值必须是常量或者全局变量
//不能这样给缺省值
void Func(int a, int b = x);//error
  1. C语言不支持缺省参数(编译器不支持)

(5)函数重载(很重要)

自然语言中,一个词可以有多重含义,人们可以通过上下文来判断该词真实的含义,即该词被重载了。

以前有一个笑话,国有两个体育项目大家根本不用看,也不用担心。一个是乒乓球,一个是男足。前者是 ” 谁也赢不了!”,后者是 “ 谁也赢不了!”

可以看出,同一句话,可能有多重意思。

  • 函数重载的概念

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

int Add(int a, int b)
{return a + b;
}double Add(double a, double b)
{return a + b;
}long Add(long a, long b)
{return a + b;
}int main()
{Add(10, 20);Add(10.0, 20.0);Add(10L, 20L);  //L表示该常数是以长整型方式存储,longreturn 0;
}
  • 思考
  • 编译器能不能实现函数名相同,参数相同,返回值不同来构成函数重载?

结论:不能实现,无法重载仅按返回值类型区分的函数

int func();    ->  _Z3ifunc
double func(); ->  _Z3dfunc

如果把返回值带进名字修饰规则,那么编译器层面是可以区分的。

但是语法调用层面,无法根据参数列表确定调用哪个重载函数,甚至带有严重的歧义!

比如这条语句 func(); ,调用时,这里是要调用哪一个呢?


(6)extern “c”

C++编译器能识别C++函数名修饰规则,也能识别C的函数名修饰规则。

  • 我们在C++项目开发中,可能会用到一些第三方的库,有些是纯C实现的库(动态库/静态库),它里面的函数名修饰规则是C的,而C++是兼容C的,C++编译器直接按照C的修饰规则去调用。

  • 如果是纯C的项目,用到C++实现的库(动态库/静态库),比如:tcmalloc是google用C++实现的一个库,他提供 tcmallc()tcfree() 两个接口来使用(更高效,替代malloc和free函数),这个库可以给C++项目用,但不能给C项目用,会存在链接失败,因为C编译器无法识别C++的修饰规则。

  • 如果想要给C用,需要将C++库中的部分函数按照C的风格来编译,在函数前加 extern "C",意思是告诉编译器,将该函数按照C的修饰规则来编译

extern "C" void Add(int a, int b);
  • 总结
  1. C++项目可以调用C++的库,也可以调用C的库。

  2. C的项目可以调用C的库,如果要调用C++的库,需要在该函数前加上 extern "C"

  • 思考题
  1. 下面两个函数能形成函数重载吗?——> 不能

    void Func(int a = 10)
    {cout << "Func(int)" << endl;
    }
    void Func(int a)
    {cout << "Func(int)" << endl;
    }
    
  2. C语言中为什么不能支持函数重载?

    ——> C和C++编译器的函数名修饰规则不一样,C编译器直接拿函数名在目标文件里面充当函数名和函数地址的映射,所以在链接的时候,是拿函数名去目标文件里面去找,函数名相同,虽然参数不同,但不知道找的是谁。

  3. C++中函数重载底层是怎么处理的?

    ——> C++编译器不直接拿函数名去找,而是拿修饰后的函数名去找,参数不同修饰后的函数名就不同,就能够找到。

  4. C++中能否将一个函数按照C的风格来编译?

    ——> 能,在函数前加上 extern "C"


未完待续,下一篇,我们将学习C++中最重要的一个知识之一,引用 …… 一起期待吧!

【C++初阶】C++入门一(命名空间、输入输出、缺省参数、函数重载等)相关推荐

  1. C++ C++基础语法入门总结(一)命名空间-输入输出-缺省参数-函数重载

    C++基础语法入门总结 C++ 命名空间 如何定义和使用命名空间 C++ 输入与输出 C++ 缺省参数 C++函数重载 名字修饰 extern "c" 推荐阅读 C++ 命名空间 ...

  2. 【C++入门第一期】命名空间 缺省参数 函数重载 的使用方法及注意事项

    目录 简介 命名空间 为何会有命名空间 命名空间的定义 嵌套定义 命名空间的使用 作用域限定符 using 将命名空间中某个成员引入 using namespace 将该空间所有成员引入 缺省参数 全 ...

  3. 【C++登山之路之语法高山 】—— 命名空间+缺省参数+函数重载(万字详解,图片演示,结构原理)

    目录

  4. SAP RETAIL初阶之事务代码MP83 显示一个预测参数文件

    SAP RETAIL初阶之事务代码MP83 显示一个预测参数文件 注:本文是一篇入门级的简单文章,仅适用于SAP REATAIL初学者,SAP零售大拿们可以跳过了. 笔者使用事务代码MP81创建了一个 ...

  5. C++入门之命名空间、缺省函数、重载函数及引用

    目录 一.命名空间 1.概念 (1)流插入运算符和流提取运算符 2.命名空间出现的意义 (1)c语言的命名缺陷 (2)如何解决命名冲突 3.命名空间的使用 (1)不展开使用 (2)完全展开使用 (3) ...

  6. 输入输出数组元素的函数重载_C ++函数重载| 查找输出程序| 套装3

    输入输出数组元素的函数重载 Program 1: 程序1: #include <iostream> using namespace std; class Test { public: vo ...

  7. 超详细的C++入门学习(命名空间,缺省参数,内联函数,函数重载等)

    目录 前言 1. C++关键字 2. 命名空间 2.1定义命名空间 2.2使用using将命名空间中某个成员引入 2.3使用using namespace 命名空间名称 引入 3. C++输入& ...

  8. C++入门:命名空间、缺省参数、函数重载、引用、内联函数、auto、范围for

    这里写目录标题 前言 命名空间 缺省参数 1.**什么是缺省参数** 2.缺省参数的分类 注意事项 函数重载 1.形参不同 2.形参顺序不同 3.形参个数不同 为什么会出现上述这样的情况呢?? gcc ...

  9. C++起始(关键字,命名空间,缺省参数,函数重载(c语言为什么不支持函数重载))

    1. C++关键字(C++98) 2. 命名空间 在C/C++中,变量.函数和后面要学到的类都是大量存在的,这些变量.函数和类的名称将都存在于全局作用 域中,可能会导致很多冲突.使用命名空间的目的是对 ...

  10. 《C++初阶之路》命名空间的意义

    一.本章重点 为什么有命名空间? 什么是命名空间? 命名空间的使用 二.为什么要存在命名空间? 我们需要知道的是:C++大多数语法的出现都是解决C语言的不足. 在C语言中,下面这样的代码能过通过编译吗 ...

最新文章

  1. 2021年SDN和NFV的支出将超1580亿美元!
  2. python查询sqlserver视图_如题:sqlserver连接Oracle数据库,在sql查询分析器中查询oracle中的视图,根据时间字段查询,SQL语句...
  3. VMware记录(一)- vCenter Server 服务安装提示无法解析此完全限定域名
  4. 我的世界源代码python_用Python写的游戏《我的世界》 还原初代世界
  5. 错误管道反应:Paul Szymkowiak和上下文驱动的思想家如何交谈
  6. 效果图底图 线框图_5分钟的线框图教程
  7. 前端学习(648):转换为boolean
  8. Java 学习第一天
  9. js面向对象数据属性和访问器属性,定义多个属性及读取属性的特性
  10. SEM搜索引擎竞价全方位系统网课-优就业-专题视频课程
  11. Fastjson存在0day漏洞
  12. Kali 利用setoolkit制作钓鱼网站
  13. 台式计算机读不到u盘怎么回事,电脑读不出u盘怎么办
  14. 网上出售企业支付宝骗局,不看后悔
  15. 社招简历老被拒?大佬告诉你面试官只中意这些简历,快来看看吧!
  16. bzoj 4318 osu 【三次方问题】【dp】
  17. 宣传册打印选择哪种纸张
  18. 数据库实验一:数据库与数据表定义(2)—— 数据表相关操作
  19. [TC6194]AllWoundUp
  20. 【想破脑袋的题】C. Grandma Capa Knits a Scarf

热门文章

  1. raid卷构建实操(raid0、raid1、raid5、raid6以及raid10),可跟做
  2. 用python代码(turtle库)绘制好看的效果图
  3. cpu利用率(cpu利用率突然100)
  4. 《通信网》专题八:接入网技术
  5. 实战案例讲解:用户画像如何应用?
  6. 北航计算机学院学硕分数,考研|北航各学院复试分数线陆续公布,原来这个专业分数最高!...
  7. 招行193亿港元收购永隆银行53.1%股份
  8. 使用vscode pull拉取报错: [rejected] (would clobber existing tag)
  9. 数字世界中的纸张——理解 PDF (转载)
  10. 常用的web服务器软件整理