一、C++入门
3. 命名空间
上次我们在命名空间部分建议大家在日常练习的时候可以展开命名空间 std ,在做项目的时候不建议展开,但是比如 cin 输入,和 cout 输出这种高频使用词不展开还是很难受的,于是还有一种比较完美的解决方法:
#include<iostream> using std::cout; int main() { cout << "Hello World!" << std::endl; return 0; }
是的,我们也可以选择只展开部分,使部分的访问权限放开,没被允许的部分仍需加上作用于限定符。这下就连高频的变量或函数就也能方便使用了。
展开部分命名空间:using space1::(变量或函数或其他名称)
这使被展开的可以不使用限定符来访问,没被展开的仍需限定符来访问。
接下来我们再看看新花样,嵌套命名空间:
#include<iostream> using namespace std; namespace space { namespace zs { void func() { cout << "zs" << endl; } } namespace ls { void func() { cout << "ls" << endl; } } } int main() { space::zs::func(); space::ls::func(); return 0; }
看看结果:
在命名空间域下可以再开辟其他的命名空间域,只要遵循域的从属关系就能轻松访问。
命名空间域可以嵌套使用,不过访问需要逐层访问。
4. 输入和输出
4.1 C++的输入符和输出符
在C++中,输入符是 cin ,输出符是 cout ,都是包含在 iostream 库里面的,咱们先了解一下,具体用法一会再说。我们先演示一遍程序:
#include<iostream> using namespace std; int main() { int input; cout << "请输入:"; cin >> input; cout << input + 1 << endl; return 0; }
结果相信很多小伙伴已经猜到了:
答案是不是跟你想的一模一样呢?
4.2 流插入和流提取
我们已经知道了 cin 和 cout 的含义,即 console in 和 console out ,从控制台获取数据,将数据out到控制台上。那 >> 和 << 是什么意思?右移和左移吗?当然不是,在C++中,祖师爷认为一个语言的长期发展,后面操作符肯定是不够用的,所以他采用了操作符复用的方法。在与输入和输出结合时, << 的意思是 流插入 ,说明将数据一个接一个像水流一样流到控制台上,于是控制台就输出了数据。很形象的,根据箭头可以看出流的方向。
4.3 自动识别类型
在C语言当中,我们需要根据数据类型来更改 scanf 或者 printf ,比如整形就需要 %d,字符类型就需要 %c 。在C++语法当中,就不需要在乎这些了,因为 cin 和 cout 是可以自动识别类型的。
#include<iostream> using namespace std; int main() { int i; char c; double d; cin >> i >> c >> d; cout << i << ' ' << c << ' ' << d << endl; return 0; }
结果如下:
endl 的全称是 end line ,意思是一行的结束。
4.4 精度控制
在C语言当中,我们是怎样控制精度的呢?假如我有一个 double 类型的变量 1.11111111 ,我想保留两位输出,那么就是这样:
#include<iostream> using namespace std; int main() { double d = 1.1111111111; printf("%.2lf\n", d); return 0; }
由于C++兼容C,所以大部分C语言代码在C++当中都能很好的运行,所以我仅仅将输出进行调整了。效果都是一样的。
结果就是:
没问题,结果符合预期,那么C++当中又是如何控制精度的呢?C++的精度控制稍显复杂,这里不再演示,仅给大家看看文档。
C++和C语言的融会贯通的,当不知道C++怎么控制精度时,可以去上网查查文档,也可以使用C语言的输出嘛,有什么方法就用什么方法。
5.缺省参数
5.1 缺省参数的概念
缺省参数是声明或定义函数时为函数的参数指定一个缺省值。在调用该函数时,如果没有指定实参则采用该形参的缺省值,否则使用指定的实参。
在C语言当中,我们是这样给函数传参的:
#include<iostream> using namespace std; void func(int a) { cout << a << endl; } int main() { func(1); return 0; }
结果如下:
就是在函数定义的部分给上参数类型和形参名,在函数调用的地方传入实参就可以调用函数。那C++中的缺省参数是怎样使用的呢?我们来看一个样例:
#include<iostream> using namespace std; void func(int a = 0) { cout << a << endl; } int main() { func(); func(1); return 0; }
让我们来看看结果:
没错,缺省参数就是在函数定义或者声明时给参数一个初始值, 当函数传入实参的时候,形参的值采用实参的值,当函数没有在相应位置传入实参时,则相应位置的形参采用默认值 。为什么要说相应位置,我们来看看下一部分。
5.2 缺省参数分类
让我们来看看更猛的。
#include<iostream> 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 << endl; } int main() { func(1, 2, 3); func(1, 2); func(1); func(); return 0; }
缺省参数可以不只有一个,所有的参数都可以缺省,我们来看看结果:
这个函数可以根据实参数量,合计有4种调用方式。那问题来了,实参传递能不能跳跃着传?答案是——当然不可以,只能从前往后传递。
上面那个函数中,所有的形参都有初始值,这种叫做 全缺省 ,就是全部形参都缺省。有 全缺省 自然有 半缺省 ,这里的 半缺省 不是只缺省一般,而是指缺省部分。并且, 半缺省的形参必须从右往左缺省 。
#include<iostream> using namespace std; void func(int a, int b = 20, int c = 30) { cout << "a = " << a << endl; cout << "b = " << b << endl; cout << "c = " << c << endl << endl; } int main() { func(1, 2, 3); func(1, 2); func(1); return 0; }
结果如下:
那么,缺省给的初始值,在声明和定义同时给吗?
#include<iostream> using namespace std; // 声明 void func(int a, int b = 20, int c = 30); // 定义 void func(int a, int b = 20, int c = 30) { cout << "a = " << a << endl; cout << "b = " << b << endl; cout << "c = " << c << endl << endl; } int main() { func(1, 2, 3); func(1, 2); func(1); return 0; }
这样写有问题吗?
哦豁,报错了,看来不能同时给,那在哪给呢,在声明给,还是在定义给,还是都可以?这里先给大家做个声明和定义分离,然后先不在声明处缺省:
head.h:
#pragma once #include<iostream> using namespace std; void func(int a);
1.cpp:
#include"head.h" void func(int a = 10) { cout << a << endl; }
test02:
#include"head.h" int main() { func(); return 0; }
结果我就不去演示了,大家可以自己去测试结果。从代码中就可以看出,主函数中 包含了头文件 ,所以调用的函数是根据头文件中的 声明 来的,声明处没有缺省,在主函数那调用的函数不给实参肯定是有问题的,所以说, 缺省参数要在声明给 ,如果声明和定义没有分离,或者没有声明,那缺省在哪就无所谓了。
缺省参数分为 全缺省 和 半缺省 ;
半缺省参数必须从右往左依次来给出,不能间隔着给;
缺省参数不能在函数声明和定义中同时出现;
缺省值必须是 常量 或者 全局变量;
C语言不支持(编译器不支持);
6.函数重载
6.1 函数重载概念
在C语言当中,是不允许出现同名函数的。但是C++可以,但是有要求,在函数名相同时,参数不同(参数个数 或 类型 或 类型顺序),才可以构成重载。
#include<iostream> using namespace std; int ADD(int a, int b) { cout << "int ADD(int a, int b)" << endl; return a + b; } double ADD(double a, double b) { cout << "double ADD(double a, double b)" << endl; return a + b; } int main() { ADD(1, 2); ADD(1.1, 2.2); return 0; }
上面代码中,两个 ADD函数 的参数不同,我们来看看主函数中调用的函数是怎样的。
细心的小伙伴或许已经发现了,这个函数调用好像是自动匹配的,int 的调用 int ,double 的调用 double 的,看来C++的语法还是非常方便的。
6.2 C++支持函数重载的原理
我们知道,C语言是不支持出现同名函数的,也就是说不支持函数重载的,那C++为啥就支持函数重载,他是在哪个地方进行了改动,才使得C++能够支持函数重载?
一个程序要运行起来,需要经过以下几个阶段:预处理,编译,汇编,链接 。在 链接 过程中, 调用函数需要找到函数的地址才能够调用函数,而在C语言当中,是 用函数名来区分函数,通过函数名来找到函数的地址 ,如果存在同名函数,那么就会因为出现区分不开的问题导致出现链接错误。
而在C++当中却有着自己的一套函数名修饰规则,函数名后面还跟着函数参数类型信息 。修饰规则我们仅仅参悟了一小部分,想详细了解C++的名称修饰规则可以上网查阅一下,我们仅仅通过知道名称后面还跟着类型信息就知道了可以借此来区分函数,所以C++依据其特殊的名称修饰规则使得他能够支持函数重载。
不同的平台会有不同的名称修饰规则,在VS当中,就是这种,后面的 H 应该就是 int ,后面的 N 应该是 double :
如果 两个函数函数名和参数是一样的,返回值不同是不构成重载的 ,因为调用时编译器没办法区分。