【C++】命名空间输入输出缺省参数函数重载
创始人
2024-01-16 16:43:35
0

​🌠 作者:@阿亮joy.
🎆专栏:《吃透西嘎嘎》
🎇 座右铭:每个优秀的人都有一段沉默的时光,那段时光是付出了很多努力却得不到结果的日子,我们把它叫做扎根
在这里插入图片描述

目录

    • 👉什么是C++👈
    • 👉C++关键字(C++98)👈
    • 👉命名空间👈
      • 命名空间定义
      • 命名空间使用
    • 👉C++输入&&输出👈
    • 👉缺省参数👈
      • 缺省参数概念
      • 缺省参数分类
    • 👉函数重载👈
      • 函数重载概念
      • C++支持函数重载的原理
    • 👉总结👈

👉什么是C++👈

  C语言是结构化和模块化的语言,适合处理较小规模的程序。对于复杂的问题,规模较大的程序,需要高度的抽象和建模时,C语言则不合适。为了解决软件危机, 20世纪80年代, 计算机界提出了 OOP(object oriented programming:面向对象)思想,支持面向对象的程序设计语言应运而生。
 1982年,Bjarne Stroustrup博士在C语言的基础上引入并扩充了面向对象的概念,发明了一种新的程序语言。为了表达该语言与C语言的渊源关系,命名为C++。因此,C++是基于C语言而产生的,它既可以进行C语言的过程化程序设计,又可以进行以抽象数据类型为特点的基于对象的程序设计,还可以进行面向对象的程序设计

在这里插入图片描述

👉C++关键字(C++98)👈

C++总计 63 个关键字,而C语言只有 32 个关键字。下面是 C++的关键字,这些关键字会在后面的博客细讲。

在这里插入图片描述

👉命名空间👈

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

看一下下面的例子:

在这里插入图片描述

此时的变量名和stdlib头文件中的rand函数冲突了,此时我们可以借助 C++的命名空间来解决这个问题。

命名空间定义

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

在这里插入图片描述

此时,我们将整型rand定义在命名空间Joy中,这就不会和库函数中的rand函数产生命名冲突了。一般来说,在开发中是用项目名字作为命名空间的名字。需要注意的是,上面程序打印的值是rand函数的地址,而不是我们定义的整型变量rand的值。那为什么会这样呢?这时候,我们就需要编译器的查找规则。

编译器的查找规则:编译器首先在局部域中找,如果在局部域中找不到,编译器就会去全局域中找。全局域中有在预处理时展开的头文件,那么编译器就在全局域中找到了rand,然后打印rand函数的地址。值得注意的是:如果在全局域中还找不到的话,编译器也不会去命名空间中找。

在这里插入图片描述

命名空间中,除了可以定义变量,还可以函数、结构体和命名空间嵌套定义等等。

namespace N1
{// 命名空间中可以定义变量/函数/类型int rand = 10;int Add(int left, int right){return left + right;}struct Node{struct Node* next;int val;};
}// 命名空间可以嵌套
namespace N2
{int a;int b;int Add(int left, int right){return left + right;}namespace N3{int c;int d;int Sub(int left, int right){return left - right;}}
}

当一个工程文件中存在着多个相同名称的命名空间,编译器最后会将里面的内容合并在同一个命名空间中。见下面的例子:

// test.h中的命名空间N1
namespace N1
{int Mul(int left, int right){return left * right;}
}// test.cpp中的命名空间N1
namespace N1
{int Add(int left, int right){return left + right;}
}

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

现在,我们已经知道了命名空间的概念了。那如何去使用命名空间里的成员呢?我们来学习一下。

命名空间使用

以下面的命名空间N为例,我们来学习命名空间的三种使用方式。

namespace N
{int a = 10;int b = 20;int Add(int left, int right){return left + right;}struct Node{struct Node* next;int val;};
}

命名空间的三种使用方式

  • 加命名空间名称及作用域限定符

    在这里插入图片描述

  • 使用using将命名空间中某个成员引入

    在这里插入图片描述

  • 使用using namespace 命名空间名称 引入

    在这里插入图片描述

👉C++输入&&输出👈

在上面讲到了命名空间可以放变量和函数的定义等等,其实 C++ 标准库的定义实现也是放在命名空间中的,这个命名空间就是std。其实这么做也是为了避免命名冲突,还可以起到保护的作用。

因为 C++标准库的定义实现都是放在命名空间中的,所以我们使用这些函数也要遵循命名空间的使用规则。

那我们现在就来用 C++ 来写一下经典的代码hello world吧!

在这里插入图片描述
知道了如何用 C++写hello world,那么我们就来学如何读取输入数据。

在这里插入图片描述
C++ 中的输入和输出可以自动识别类型,这是相较于C语言中scanfprintf的优势。不过想要用coutcin控制浮点数输出精度,控制整形输出进制格式等等,这就会比较复杂了。这时候,我们就可以结合着 C语言来使用,就是那个使用起来方便就使用哪一个。见下图:

在这里插入图片描述

注意:以上的将命名空间的内容展开这种使用方式是简单了,但是标准库就全部暴露出来了,就有可能存在命名冲突问题。不过,我们在日常练习或者写小程序的时候可以这样写,但是在项目里最好不要用。除了将命名空间全部展开,我们还可以将常用的指定展开,如using std::cout,只需要注意定义变量或者函数的时候避免命名冲突就可以了。

说明:

  • 使用cout标准输出对(控制台和cin标准输入对象键盘时,必须包含iostream头文件 以及按命名空间使用方法使用std。
  • cout和cin是全局的流对象,endl是特殊的C++符号,表示换行输出,他们都包含在包含< iostream >头文件中。
  • <<是流插入运算符,>>是流提取运算符
  • 使用C++输入输出更方便,不需要像printf/scanf输入输出时那样,需要手动控制格式。 C++的输入输出可以自动识别变量类型
  • 实际上cout和cin分别是ostream和istream类型的对象,>>和<<也涉及运算符重载等知识, 这些知识我们我们后续才会学习,所以我们这里只是简单学习他们的使用。后面我们还有有 一个章节更深入的学习IO流用法及原理。

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

👉缺省参数👈

缺省参数概念

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

这是什么意思呢?请看下方代码:

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

在这里插入图片描述

缺省参数分类

  • 全缺省参数
#include 
using namespace std;void Func(int a = 10, int b = 20, int c = 30)
{cout << "a = " << a << endl;cout << "b = " << b << endl;cout << "c = " << c << endl;
}int main()
{Func();Func(1); // 传给第一个Func(1, 2); // 传给第一个和第二个Func(1, 2, 3);//Fun(1, , 3); // 错误的调用方式return 0;
}

在这里插入图片描述

  • 半缺省参数
#include 
using namespace std;void Func(int a, int b = 10, int c = 20)
{cout << "a = " << a << endl;cout << "b = " << b << endl;cout << "c = " << c << endl;
}int main()
{Func(1);return 0;
}

有了缺省函数,我们就可以有下面的玩法了。

#include 
struct Stack
{int* a;int top;int capacity;
};void StackInit(struct Stack* ps, int defaultCP = 4)
{ps->a = (int*)malloc(sizeof(int) * defaultCP);assert(ps->a);ps->top = 0;ps->capacity = defaultCP;
}int main()
{// 不知道要插入多少数据struct Stack st1;StackInit(&st1);// 知道要插入100个数据struct Stack st2;StackInit(&st2, 100);
}

注意

  • 半缺省参数必须从右往左连续缺省,不能间隔缺省
  • 缺省参数不能在函数声明和定义中同时出现。如果声明与定义位置同时出现,恰巧两个位置提供的值不同,那编译器就无法确定到底该用那个缺省值。
  • 缺省值必须是常量或者全局变量
  • C语言不支持(编译器不支持)

👉函数重载👈

自然语言中,一个词可以有多重含义,人们可以通过上下文来判断该词真实的含义,即该词被重载了。比如:以前有一个笑话,国有两个体育项目大家根本不用看,也不用担心。一个是乒乓球,一个是男足。前者是“谁也赢不了!”,后者是“谁也赢不了!”

函数重载概念

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

参数类型不同

#include 
using namespace std;int Add(int left, int right)
{return left + right;
}double Add(double left, double right)
{return left + right;
}int main()
{cout << Add(1, 2) << endl;cout << Add(1.1, 2.2) << endl;return 0;
}

在这里插入图片描述

这也是 C++ 相较于 C语言的优势,其实就是编译器能够自动识别类型,本质就是函数重载支持。

个数不同

#include 
using namespace std;void f()
{cout << "f()" << endl;
}void f(int a)
{cout << "f(int a)" << endl;
}int main()
{f();f(1);return 0;
}

在这里插入图片描述

顺序不同

#include 
using namespace std;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(0, 'A');f('A', 0);return 0;
}

在这里插入图片描述
注意:顺序不同是形参类型顺序不同,以下的代码不是顺序不同,并不构成函数重载。

void f(int b, int a)
{cout << "f(int b, int a)" << endl;
}void f(int a, int b)
{cout << "f(int a, int b)" << endl;
}

含数重载与缺省参数

#include 
using namespace std;// 构成函数重载
void f()
{cout << "f()" << endl;
}void f(int a = 0, char b = 1)
{cout << "f(int a, char b)" << endl;
}int main()
{f(10);f(10, 20);return 0;
}

注意:以上的函数构成函数重载,但是调用f()会报错,存在歧义。

C++支持函数重载的原理

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

在C/C++中,一个程序要运行起来,需要经历以下几个阶段:预处理、编译、汇编、链接。C /C++在编译链接的时候,会生成符号表。不过 C语言 和 C++ 生成的符号表是不一样的。C语言的符号表直接是函数名+地址,而 C++ 的符号表是经过修饰后的函数名+地址。所以 C语言不会支持同名函数,也就是不支持函数重载,而 C++是支持函数重载的。

在这里插入图片描述

结论:在 linux 下,采用g++编译完成后,函数名字的修饰发生改变,编译器将函数参数类型信息添加到修改后的名字中

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

Windows下名字修饰规则

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

相信大家都知道函数名修饰规则,那我问大家一个问题:. 如果两个函数函数名和参数是一样的,返回值不同是否构成函数重载。相信很多同学可能会说构成函数重载,因为我们只需要在函数名前面加上函数的返回值类型标识就好了。其实这不是真正的原因,就算函数名修饰时加上函数的返回值类型也会出现问题,因为在调用函数的时候没有办法指定函数的返回值类型。

在这里插入图片描述

函数名和参数是一样的,返回值不同的函数不构成重载的真正原因并不是函数名修饰规则,而是调用时的二义性,调用时不指定函数的返回值类型,无法区分调用哪一个函数。

👉总结👈

在本篇博客里,我们学习了C++的命名空间、输入和输出、缺省参数以及函数重载。这也意味着我们已经步入了C++,希望我们一起努力吃透C++。以上就是本篇博客的全部内容了,如果大家觉得有收获的话,可以点个三连支持一下!谢谢大家啦!💖💝❣️

相关内容

热门资讯

后进生评语 【推荐】后进生评语11篇  在日常的学习、工作、生活中,许多人都写过评语吧,评语于细微之处肯定被评价...
家长评价学生的评语 家长评价学生的评语  评语的引证解释  清唐鉴《廪贡生王府君墓志铭》:“昔年官京师,阅倭艮峯日记,见...
运动会横幅口号 运动会横幅口号(精选90句)  在平时的学习、工作或生活中,大家一定都接触过一些使用较为普遍的口号吧...
清仓大甩卖广告词整理 清仓大甩卖广告词整理  在学习、工作、生活中,大家都接触过比较经典的广告词吧,广告词具有为企业塑造品...
班级的励志标语 关于班级的励志标语  无论是身处学校还是步入社会,说到标语,大家肯定都不陌生吧,作为一种最经济、最有...
安全横幅的标语 安全横幅的标语(精选125句)  在平日的学习、工作和生活里,许多人都接触过一些比较经典的标语吧,标...
企业服务的宗旨标语   最大限度地满足患者的需求,最快速度地为病人服务。企业服务的宗旨标语有哪些?相信很多人都想知道吧?...
校园安全标语 校园安全标语(精选121句)  安全,安全,安全是人们生存的基本,下面是小编为大家收集的校园安全标语...
安全质量口号 安全质量口号  一、在项目部、施工现场、道路岔口和重要的施工位臵等处的安全标语和警示语  1、以人为...
苏宁电器广告语 苏宁电器广告语苏宁电器广告语1  1、精品荟萃,微利可见,长润家电,说明长润家电物全价廉。  2、长...
高中生学生评语大全 高中生学生评语大全  在平凡的学习、工作、生活中,大家都写过评语吧,评语可以帮助被评价者不断地逼近理...
吸引人的爱心义卖口号 吸引人的爱心义卖口号  在生活、工作和学习中,大家都接触过很多优秀的口号吧,口号能指导人们有效地开展...
心理健康教育宣传标语 心理健康教育宣传标语(精选280句)  无论是在学校还是在社会中,大家都看到过标语吧,借助标语可以达...
环保标语口号 环保标语口号大全  小草才露尖尖头, 莫让鞋印踩上头 让优雅的环境与美好的心灵同在,环保标语口号大全...
奶茶店活动标语 奶茶店活动标语(精选380句)  在我们平凡的日常里,大家都看到过标语吧,标语不但折射着时代精神,也...
幼儿园安全工作会议记录 幼儿园安全工作会议记录(精选9篇)  做好安全教育工作,普及安全知识。利用各类会议、通知、板报、标语...
小学班级口号 小学班级口号300句  在现实生活或工作学习中,大家都对那些朗朗上口的口号很是熟悉吧,口号往往带有很...
增员口号-口号标语大全   1、增员无师父,耐心就增有。  2、寿险生命的意义在增员。  3、有员千里来相助,育组报答万里情...
小学班主任评语 精选小学班主任评语  在平日的学习、工作和生活里,大家对评语都不陌生吧,评语的内容、格式、你会写评语...
法制宣传主题标语 法制宣传主题标语(精选175句)  在日常学习、工作和生活中,许多人都接触过一些比较经典的标语吧,标...