C++入门
—————————————————————————————————
1.命名空间
在C++学习中,函数名、变量等都会大量存在。它们存在与全局作用域中,可能会产生很多冲突。我们为了避免冲突,使用命名空间将这些标识符本地化。
下面先看一段代码
图中发生了错误,原因是变量rand重定义了。
这时会有疑问?明明只定义了一次全局变量rand,怎么重定义了?
原因其实是stdlib.h这个头文件。在编译时,头文件中的内容会在全局作用域中展开,其中就包括rand()。头文件中的rand是一个函数的名字,而如果我们在全局中再定义一个rand变量,自然就会发生冲突。
那么该怎么解决呢?显然就用到命名空间了。
我们定义了一个命名空间,namespace是定义命名空间时的关键字,yang是这个空间的名字。此时我们在打印一下rand,就成功了。
但是要注意,打印时要指定命名空间中的rand,语法为yang::rand。
::是作用域限定符。
命名空间也有很多用法
命名空间可以定义函数、变量
命名空间里面还可以嵌套命名空间
一个工程中允许存在多个名称相同的命名空间,编译器会将他们合并成一个。
在头文件test.h中也定义命名空间N1,其中定义了变量x;
在study.cpp中定义了N1,其中定义变量a。
最后程序执行成功,说明两个文件中的N1确实是同一个命名空间。
2.输入和输出
C++语句会与C语言稍不同,其中就包括cout和cin。
cout是标准输出对象(控制台),cin是标准输入对象(键盘)。<<是流插入运算符,>>是流提取运算符。
要点:
1.使用cout和cin时,程序必须包含iostream头文件以及按照命名空间正确使用std。
2.endl是C++中特殊的符号,它类似于C语言中的换行。
3.cout、cin、endl都存在在iostream头文件中。
4.C++的输入输出不用向C语言那样需要手动指定格式,它可以自动识别变量类型。
std是c++标准库的命名空间,在平时练习使用时,我们可以直接using namespace std。但是当我们在做项目时,最好还是按照std::cout或者using std::cout这样的方式来使用。因为直接using namespace std会将空间全部展开,项目中往往会用到大量的变量和函数,因此很有可能冲突。
3.缺省参数
在声明或定义函数时,可以给参数一个缺省值,这样如果使用函数而没有传递实参,函数就使用对应的缺省值;如果传递了实参,则就使用实参。注意声明和定义不能同时给缺省值。如图
全缺省参数
函数的每个参数都有缺省值。如图func1,它的参数就是全缺省参数。
半缺省参数
函数的参数不都是缺省参数,而且缺省参数必须是从左到右连续的。
这里func2就是半缺省参数。但如果func2是下图这样
这样func2就不是半缺省参数,因为缺省参数没有从左到右连续存在,而且编译器也会报错。
4.函数重载
C++中,对于功能相似的几个函数,允许它们的函数名相同,参数列表不同(个数、类型或参数顺序)。
为什么c语言不能函数重载,而c++可以?
原因是函数命名修饰规则。
c/c++程序,需要经过预处理、编译、汇编、链接四个阶段。
如果一个项目中有两个文件a.cpp和b.cpp,后者中有一个add函数,前者程序中使用了add函数。在编译后连接前,文件会形成符号表。链接器在a.o中发现使用了add,但是没有找到add的地址,它就会去b.o的符号表中寻找,等找到add的地址后将他们链接在一起。
那么在链接时,链接器会根据什么名字寻找呢?这里是,每一个编译器都有一个函数名修饰规则。如linux中gcc对c语言修饰规则,修饰后函数名字没有发生变化。而g++对c++修饰后,函数名字发生变化,并且修饰后的名字与函数名、参数类型都有关系。
所以到这里应该就明白了为什么c语言不支持函数重载,因为函数修饰后同名函数无法区分。而c++支持,是因为函数修饰与函数名和参数都有关系,同名函数只要参数不同,就可以区分。
注意一点,如果两个函数函数名和参数是一样的,返回值不同是不构成重载的,因为调用时编译器没办法区分
缺省参数和函数重载
图中func()是不是函数重载,答案是重载。因为符合函数重载的定义,但是又有点不同,就是这两个函数不能同时出现。
错误原因是有歧义或者说二义性,因为main函数不知道这个func到底是哪一个,无法区分。