1.函数的声明可以不包含参数名,只定义类型,即使包含了,编译器也会忽略掉。
2.函数的定义时,可以将不命名,只定义类型的参数作为保留以后添加,而不会影响函数的调用。
3.static 声明的局部变量,实质是将局部变量的生存周期延长至整个程序,但不会改变其作用域。即多次调用函数,该静态变量都只是同一个存储位置的变量,不会有其他副本。
4.注意传参的时候,C++比C多了传引用&的形式。
5.注意const的使用,const用于限制对传入参数的修改很有效。const和&的结合const&,特许文字量,常量,和需要转换的参数作为引用参数传入函数,而普通引用参数是不允许的,因为存在有更改的可能,强转时候就变成了副本而非原来的变量,与其希望修改的初衷不符。对于非引用参数来说,const只是对其函数内部的使用有限制,对传参无限制。
6.数组传参,是传入的指针,而非数组,所以函数的参数一定是指针,一定不是传值的形式。指针参数也可以用const,也是无法修改值的意思。
7.返回值:千万不要返回局部变量的指针,其地址在函数返回之后会留作他用 ,但是可以返回局部变量的值,因为会返回一个副本。
对于void返回值类型,存在一种特殊情况,就是返回一个返回值为void的函数,这样就相当于在返回前调用一下该函数,用作递归很有效简单.
9.默认参数:对函数的参数,不像变量一样,不初始化会默认值,这里需要对可能不赋值的参数声明时指定默认值。void print(int x,int y =2);注意默认参数必须放在最后,否则无法确认是否算作赋值。
10.变参::在参数表最后用…表示。典型的printf()就是这样的函数。要想在函数中获得变参的信息,有< cstdarg>提供了标准宏VA_LIST.
1.首先在函数里定义一具va_list型的变量ap,这个变量是指向参数的指针; 2.然后用va_start宏初始化刚定义的VA_LIST变量,va_start(ap,最后一个定义参数的名字); 3.然后用va_arg返回可变的参数,VA_ARG的第二个参数是你要返回的参数的类型(如果函数有多个可变参数的,依次调用VA_ARG获取各个参数); va_arg(ap,类型); 4.最后用va_end(ap)宏结束可变参数的获取.11.指向函数的指针:对函数的调用,不只是直接使用其名字直接调用,还可以使用其地址的指针来调用。 函数指针的声明与变量指针的声明思路相同,也是用指针*指向实际的类型,不过这里是类型是函数的包括变量,返回值的一个整体,相当于用(*指针名)替换实际的函数名,而做出的一个变量声明。 函数指针的使用与变量指针的使用大同小异,同在都是使用&来赋值,这里用(&函数名)来赋值;异在这里还可以直接用(函数名)赋值。同在都是用(*p)来解析指针,异在这里还可以直接用p(变量)调用函数。一般可以为其定义一个别名,方便使用。如sort()中的cmp变量就适合设计成函数指针,便于赋值不同的函数。
1.名字空间不只是namespce显式生成的,类,全局作用域,其他局部作用域也算是建立在名字空间的概念之上的。名字空间突破了{}划分作用于的物理限制,实现了一种基于声明的逻辑分组。
2.针对声明建立的逻辑分组:重在声明的位置,而不是定义。
3.一般可以通过在名字空间中声明,而通过::的形式在其他地方定义的方式实现模块的界面和实现分离。注意:::只能对名字空间里声明了的成员定义,不能用::做添加成员的作用。当然可以也是在namespce直接定义的。 4.使用::来使用另一个namespace中的成员,而自己所在的namespce中的成员可以直接调用或访问,所以有时会看看到使用了没有在其函数内部声明的变量或函数调用,这时可以看看其所在名字空间的声明中。
5.关键字using:使用using namespce 空间名 来引用整个名字空间,或者using 函数名 来引用某个函数。与include 类似,但是using更像一个语句,可以在函数局部使用,也可以直接在namespace声明中使用,相当于一个外部链接。
6.名字空间在代码移植上也很有用,用来区别不同来源的代码,避免名字冲突。
7.using指令存在会污染名字空间的作用,毕竟引入了一个异物,而并不是所有成员都想使用它。最好是在具体使用它的函数空间内使用using指令。有一种情况是可以不显式限式函数,而使用显式限定其参数的形式,编译器也会在其参数类型(往往为特殊类型)所在的namespace中寻找该函数。有前提是,在调用该函数的作用域中声明的该名字空间,而且被调用的函数在调用前已经定义。这种情况多用于运算符重定义函数,如==。
8.别名:namespace s=std
9.namespace的组合:using 指令可以用作跨空间访问和定位成员函数,但是并不能用作跨空间定义成员。即必须使用实际定义所在的空间名来限定函数,才能对其定义,而不能用其他一个using了函数所在空间的空间名。
10.using只是对函数名引用,即不带参数,这样就可以把所有重载类型都引用进来。重载可以跨空间,多个空间中的同名函数。即引用的多个名字空间中,不能有重名函数,除非使用了using优先声明了某个函数。
11.使用using 特定成员的形式要比using整个空间更优先,即会先匹配前者。
12.名字空间是开放的,即可以随时随地使用namespce为其加入成员,也可以将声明展示出来,这是一个空间不同界面的基础,用户看不到的就不会用。
1.异常是模块化的产物,因为模块化就意味着信息不对等,使用者不明白实现者的内部机制,实现者不清楚使用者希望的处理方式。所以就有了抛出异常的实现者方式(错误报告),以及检测异常并抓住异常的处理者方式(错误捕获)。
2。throw 语句就是相当于返回一个后面指定实例。catch语句会指定一个类型,用类型于返回的类型匹配,只要类型一致,就会把返回的实例赋值给指定的变量,并进入该catch的作用域,在该作用域里就可以使用该实例来分析错误。
3.异常与返回的区别在于,异常携带异常信息,会有一个catch的处理机制,相当于分离出来的一个返回类型。 异常与错误的区别在于,异常会被捕获,做出一些处理再结束。
4.C++没有java中的finally,少了一些操作,但是局部变量也是会自动析构的。
1.源文件和编译单位:由源文件include引进头文件之后的预处理文件,为编译单位。而实际中将不同文件中程序联系起来作为一个整体的编译单位处理的机制是连接器。
2.#include <标准库中的文件> #include <其他头文件 > 对于每个C标准库文件< X.h>,都存在一个标准库中的< cX>(在其中实现了将C函数放进std空间的操作以及为调用文件直接提供一个using namespace std的操作,这样主要是为了C语言代码的兼容,因为否则就需要在C语言里加入之前没有的namespace的语句。
3.一般的头文件中只有声明,这样也就节省了编译负担。
4.注意即使在不同的编译单元中,全局空间只有一个,即所有{}之外的空间。也称共享空间,这是不同编译单元通信的手段。头文件就是在全局空间中。
4.在不同源文件中可以对同一个实现定义两个,但是前提是在不同的编译单位中,即.c中,而且对应的定义完全相同。
5.extern可以置于变量或者函数前,以标示变量或者函数的定义在别的文件中,提示编译器遇到此变量和函数时在其他模块中寻找其定义。 extern “C” void fun(int a, int b);则告诉编译器在编译fun这个函数名时按着C的规则去翻译相应的函数名而不是C++的. 在头文件中: extern int g_Int; 它的作用就是声明函数或全局变量的作用范围的关键字,其声明的函数和变量可以在本模块活其他模块中使用,记住它是一个声明不是定义 extern int i; //声明i而非定义,定义即初始化 int j; //声明并定义i,默认定义
下面是extern的作用,即声明某个函数或变量在其他编译单元有定义。如果没有这样的定义,就无法在该编译单元里使用该函数。一般因为不在头文件中定义,所以会在头文件的声明中使用这样的关键字,这样可以在没定义该函数的编译单元里表明会有一个编译单元有这些定义,而在有定义的单元里,extern也就没什么意义了,虽然它也include的时是同一个头文件。如果不加extern的头文件,就必须定义成员,不然也是无法通过编译的。
// file1.cpp #include <iostream> int i; // file2.cpp #include <iostream> extern int i; int main() { i = 100; return 0; };6.可以为同一个名字空间设置不同的头文件,就可以实现不同的界面,虽然实现界面可以和定义在一起,但是最好也是分出一个实现界面来。然后在一个.c文件中专门定义,它需要引入实现界面的头文件。
7.全局变量,名字空间变量,类的static变量会在main函数之前完成初始化,按顺序。而不同编译单位里全局变量的编译顺序并不确定。
8.程序终结:main函数返回;exit()(静态对象的析构函数会调用,但是局部变量不会析构)(cstdlib) abort()(静态对象的析构函数不会调用);没捕捉的异常(局部变量会析构);
