文章目录
【C++笔记】C++基本语法和命名空间
前言
hello,屏幕面前正在学技术的你,相信你也想快速仔细学完c++,类与对象是c++基础的基础也是重中之重,话不多说,让我们一起来看看吧!
一.命名空间
1.1namespace的价值
在C/C++中,变量、函数和后⾯要学到的类都是⼤量存在的,这些变量、函数和类的名称将都存在于全局作用域中,可能会导致很多冲突。使⽤命名空间的⽬的是对识符的名称进⾏本地化,以避免命名冲突或名字污染,namespace关键字的出现就是针对这种问题的。
c语言项目类似下面程序这样的命名冲突是普遍存在的问题,C++引⼊namespace就是为了更好的解决这样的问题。
#include <stdio.h>
#include <stdlib.h>
int rand = 10;
int main()
{
printf("%d\n", rand);
return 0;
}

这段代码是编译不过的。因为rand在<stdlib.h>头文件是一个函数。全局变量又有一个rand变量。所以就会产生命名冲突。因为在同一个域里不能定义名变量或函数。那如何解决呢?这就得使用我们的命名空间了。
namespace niuma
{
int rand = 20;
}
int rand = 10;
int main()
{
printf("%d\n", rand);
return 0;
}
这时候我们使用namespace关键字创建一个名为qcj的命名空间。命名空间本质是一个域——命名空间域。不同域可以定义同名变量或函数。这就解决了命名冲突的问题。
域作用限定符
编译器查找变量或函数时遵循就近原则。先查找当前局部域,再到全局域找。两个都找不到就报错。不会去命名空间域找。那如果我们要访问命名空间域的变量如何访问。就需要域作用限定符——::指定域。

但是需要注意的是。结构体指定域需要放在右边不是左边。
1.2namespace的定义
定义命名空间
定义命名空间,需要使用到namespace关键字,后⾯跟命名空间的名字,然后接⼀对{}即可,{}中即为命名空间的成员。命名空间中可以定义变量/函数/类型等。
命名空间域
namespace本质是定义出⼀个域,这个域跟全局域各自独立,不同的域可以定义同名变量,所以前面的rand不在冲突了。
所有域
C++中域有函数局部域,全局域,命名空间域,类域;域影响的是编译时语法查找⼀个变量/函数/类型出处(声明或定义)的逻辑,所有有了域隔离,名字冲突就解决了。局部域和全局域除了会影响编译查找逻辑,还会影响变量的生命周期,命名空间域和类域不影响变量生命周期。

嵌套定义
namespace只能定义在全局,当然他还可以嵌套定义。
例如在做项目时,每个接口的实现可以封装一层命名空间。项目的每个人又可以有自己的命名空 间。这时我们只需要一层一层指定即可。
多文件定义
项目工程中多文件中定义的同名namespace会认为是⼀个namespace,多个相同命名空间的内容会自动合并成一个。不会冲突。
标准库
C++标准库都放在⼀个叫std(standard)的命名空间中。
1.3命名空间使用
编译查找⼀个变量的声明/定义时,默认只会在局部或者全局查找,不会到命名空间⾥⾯去查找。所以我们要使⽤命名空间中定义的变量/函数,有三种方式:
指定查找
指定命名空间访问,项目中推荐这种方式。
但是每次都需要指定不太方便。这时就可以展开。
-全部展开
使用using关键字将命名空间全部成员展开,这样就不需要指定域查找。
展开命名空间中全部成员,项目不推荐,冲突风险很大,日常小练习程序为了方便推荐使用。
namespace niuma
{
int rand = 20;
}
using namespace qcj;
int main()
{
printf("指定:%d\n", rand);
return 0;
}
成员展开
using将命名空间中某个成员展开,项目中经常访问的不存在冲突的成员推荐这种⽅式。如果经常使用某个成员并且不冲突时可以展开该成员。
namespace niuma
{
int rand = 20;
}
using qcj::rand;
int main()
{
printf("指定:%d\n", rand);
printf("指定:%d\n", rand);
printf("指定:%d\n", rand);
printf("指定:%d\n", rand);
return 0;
}
二.C++输入&输出
2.1 IO流
在介绍IO流之前先给各位小伙伴们推荐几个好用的c++学习网站,第一个是c++官网https://zh.cppreference.com/w/cpp 第二个是https://legacy.cplusplus.com/reference/ ,第二个不是c++官方文档,但是以头文件形式呈现,内容对于初学者来说比较友好,第一个是c++的英文版,不推荐中文版的原因是,如果学到后期,学到c++的最新标准,那么我们最好就是根据英文文档来看,中文因为翻译的原因肯定没有纯英文版表达的意思那么充分
1.iostream
《iostream》是InputOutputStream的缩写,是标准的输入、输出流库,定义了标准的输入、输出对象。
2.cin
std::cin 是istream类的对象,它主要面向窄字符(narrowcharacters(oftypechar))的标准输入流。
3.cout
std::cout 是ostream类的对象,它主要面向窄字符的标准输出流。
为了方便运算整数浮点数在内存中才有原反补码,在文件,网络都是以字符形式输入输出。
4.endl
std::endl 是⼀个函数,流插入输出时,相当于插入⼀个换行字符加刷新缓冲区。
流插入和提取
<<是流插入运算符,>>是流提取运算符。(C语言还用这两个运算符做位运算左移/右移)
自动识别
使用C++输入输出更方便,不需要像printf/scanf输入输出时那样,需要手动指定格式,C++的输入输出可以自动识别变量类型(本质是通过函数重载实现的,这个以后会讲到),其实最重要的是C++的流能更好的支持自定义类型对象的输入输出。
标准库
cout/cin/endl等都属于C++标准库,C++标准库都放在⼀个叫std(standard)的命名空间中,所以要通过命名空间的使用方式去用他们。
间接包含
这里我们没有包含<stdio.h>,也可以使用printf和scanf,在包含间接包含了。vs系列编译器是这样的,其他编译器可能会报错。
精度控制
C++控制精度需要使用对应的函数。较为复杂。所以建议直接使用scanf和printf即可。因为C++兼容C。
IO效率
我们C++就要兼容C语言。我们控制台输入输出还需要通过缓冲区。C++和C语言各自有各自的缓冲区,要兼容C语言就还需要关注C语言的缓冲区。这样就会付出一些代价降低效率。
int main()
{
// 在io需求⽐较⾼的地⽅,如部分⼤量输⼊的竞赛题中,
//加以下三⾏代码 可以提⾼C++IO效率
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
}
return 0;
加上这三行代码就可以提高效率。
三.缺省参数
缺省参数是声明或定义函数时为函数的参数指定⼀个缺省值。在调用该函数时,如果没有指定实参则采用该形参的缺省值,否则使用指定的实参,
缺省参数分为全缺省和半缺省参数(有些地方把缺省参数也叫默认参数)
如果传参就使用指定参数,不传参就使用缺省参数。
#include <iostream>
#include <assert.h>
using namespace std;
void Func(int a = 0)
{
cout << a << endl;
}
int main()
{
Func(); // 没有传参时,使⽤参数的默认值
Func(10); // 传参时,使⽤指定的实参
return 0;
}
全缺省
全缺省就是全部形参给缺省值。不管有多少个参数都给了缺省参数。调用的时候可以无参也可以带参。
// 全缺省
#include <iostream>
#include <assert.h>
using namespace std;
void Func(int a = 0)
{
cout << a << endl;
}
int main()
{
Func(); // 没有传参时,使⽤参数的默认值
Func(10); // 传参时,使⽤指定的实参
return 0;
}
半缺省
半缺省就是部分形参给缺省值。
注意:C++规定半缺省参数必须从右往左依次连续缺省,不能间隔跳跃给缺省值。
//
半缺省
void Func2(int a = 10, int b , int c = 20)
{
cout << "a = " << a << endl;
cout << "b = " << b << endl;
cout << "c = " << c << endl << endl;
}
不能这样跳跃给。
// 半缺省
void Func2(int a, int b = 10, int c = 20)
{
cout << "a = " << a << endl;
cout << "b = " << b << endl;
cout << "c = " << c << endl << endl;
}
只能从右到左给。
函数调用
带缺省参数的函数调用,C++规定必须从左到右依次给实参,不能跳跃给实参。
声明和定义分离
函数声明和定义分离时,缺省参数不能在函数声明和定义中同时出现,规定必须函数声明给缺省值。
四.函数重载
C++⽀持在同⼀作⽤域中出现同名函数,但是要求这些同名函数的形参不同,可以是参数个数不同或者类型不同。这样C++函数调用就表现出了多态行为,使用更灵活。C语言是不支持同⼀作用域中出现同名函数的。
函数重载可以更方便我们编写代码。同时也更加灵活。
个数不同
函数个数不同构成函数重载。
void f()
{
cout << "f()" << endl;
}
void f(int a)
{
cout << "f(int a)" << endl;
}
int main()
{
f();
f(1);
return 0;
}
类型不同
类型不同也构成函数冲宅重载。
// 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(1, 3);
Add(1.3,4.5);
return 0;
}
顺序不同
顺序不同构成函数重载。
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(1, 'a');
f('a',1);
return 0;
}
调用歧义
返回值不同不能作为重载条件,因为调用时也无法区分
void fxx()
{
}
int fxx()
{
}
int main()
{
fxx();
return 0;
}
但是这两个函数构成重载也编译不过。
void f()
{
cout << "f()" << endl;
}
void f(int a=10)
{
cout << "f(int a)" << endl;
}
int main()
{
f();
return 0;
}
因为这两个函数调用存在歧义,编译器不知道调用谁。
479

被折叠的 条评论
为什么被折叠?



