看完C++ Primer的第七章,觉得这一章值得被一看再看,现写了一些总结,尽量囊括知识点,但绝不冗余,力求简单易懂。
第七章的题目是 函数
定义:
int add ( int x, int y) {}
前面的int为返回参数类型。函数在定义时必须声明函数的返回类型(除了类的构造函数以及析构函数)
add 是函数名,同时也是函数的地址。(这一句很重要):
括号内 是形参表,其中的形参便是在这里定义,在函数调用时进行初始化的。
{}内是函数体。函数体本身是构成一个作用域。遵循作用域的原则。
参数传递:
非引用形参:对形参初始化之后,实参就没事干了。函数体的操作都是形参的事。
1 指针形参:指针的值(某个东西的地址)赋给形参之后,就相当于把实参指向的东西的地址给了形参,形参就去操作指针指向的值了。如果参数有const,那么就不允许修改。
例如:
void changePtrTo(int *p)
{
*p = 1; //p出卖了指向的值的地址(即它自身的值),指向的值被改变啦
p = 0; //p本身却没有变
}
对于加入 const 的参数,说明函数内部不能修改该形式参数的值(因为是传值调用),因此传给它const 或者是非const都可以。
但是,在 需要修改实参的值 、 实参的对象比较大,复制很耗时、没有办法实现对象的复制时,引入了引用形参。
引用形参:
当函数要返回两个内容的时候,可以将一个内容的指针或者是引用作为形参。
避免大型对象的复制。
其他形参:
vector 或者其他容器类型 ,为了避免,可以直接将该容器的起始与结尾的迭代器作为参数。
数组形参: 数组会退化为指针,指向数组头结点的指针。通常直接将数组名当做指针传入。如果指定了指针的长度,C++编译器会直接忽略不管,因此下述3种定义是等价的:
void Func(int *a);
void Func(int a[]);
void Func(int a[10]);
但是如果传递的是数组的引用,那么数组名就不会退化为指针,而是当做数组来处理,如:
void Func(int (&arr)[10] );//该函数只接收数组大小为10的数组!!
对于多维数组的传递,跟定义一样,指明第二维 的大小即可。
对于参数的数目是可变的,void foo(parm_list,...),用三个点即可。
函数的返回值:
main函数的返回值,建议使用不依赖于机器的 EXIT_SUCCESS与EXIT_FAILURE.
返回非引用类型,创建一个临时对象返回,返回调用处即可。
返回引用类型。(不可返回局部对象的引用或者是指向局部对象的指针)
返回左值(竟然还有这样的!!)
int getElem(int A[], int index)
{
return A[index];
}
上述函数返回的是数组的元素,因此可以有 getElem(A, 2 ) = 5;表示将数组的第2个元素赋值为5.
函数声明:
默认实参 :
int add(int x, int y = 0, int z = 3); //默认实参的位置必须是参数表的某后缀!!!
注意:默认实参只能在函数声明和函数定义中 出现一次。
类的成员函数:
定义在函数体内部的,自动编译为内联函数。
每一个类的成员函数都有一个隐式的参数this指针。指的是调用这个函数的对象的地址。(除static之外)
常成员函数,就是在函数声明的某位加上const,表示调用该函数的对象不可以被修改。
构造函数:
与类同名、 无返回值、不同的构造函数应该有不同的类型或数目的形参。
没有参数的构造函数叫做默认构造函数。
如果没有定义构造函数,编译器会自动生成一个 “合成默认构造函数”,类内部的成员变量按照自己的初始化方式进行初始化。(次初始化的方式取决于该对象的定义的位置。全局/局部)。
重载函数
相同作用域下的两个函数,同名字但是形参表不同。
main不能重载。
下面的几种情况都不能称为重载:
int add(int x);
int add(int); //函数在调用时只会检查形参的类型,形参名是会被忽略的。
typedef unsigned char BYTE;
int add(unsigned char);
int add(BYTE ); //两者的形参类型是完全一致的
int add(int x, int y = 3);
int add(int x, int y);//第一个函数有默认参数,但是它的调用时包含了第二种情况的
int add(int x);
int add(const int x);//const不能作为重载的标志。(但是这仅限于非引用类型)
对于const的引用类型以及指向const的指针作为形参时,const是可以作为重载的标志的。
当调用某个重载函数时,究竟调用哪个。取决于:1 每个实参的匹配都优于其他的候选者。或者是 2 至少有一个实参的匹配优于候选者。
实参匹配优先级:
精确匹配 -- > 类型提升 -->标准转换 -- > 类类型转换。
int (*pAdd) (int , int);
将函数名处替换为指针表示即可,与定义int型指针式一样的,比如:
int x;
int *p;
int add(int ,int);
int (*pAdd)(int , int);
由于函数名实际上是函数的地址,因此可以用函数名初始化函数指针。
pAdd = add;
函数指针可以作为函数的参数,还可以作为返回值。
int (*ff(int))(int *, int);
指向重载函数的指针,由于重载本身的不确定性,因此要求实参与形参的匹配必须是精确匹配。
完毕!觉得这一章的东西主要是围绕函数来进行的。读完此章,获益匪浅。