《C++ Primer》第7章 函数

C++ 函数

函数由 返回类型 函数名 (形参表) 唯一表示。

函数每次调用都会重新创建函数所有的形参,此时所传递的实参将会初始化所对应的形参。

形参初始化与变量初始化一样,如果形参为非应用类型,则复制实参值;如果形参为引用类型,则用实参地址初始化形参。

如果函数的形参为非引用、非const,则实参是不是const 都无所谓,实际传入函数的为实参的副本;如果形参为const 则不允许修改传入的实参副本。

当在函数中需要修改实参的值;

当实参为大型对象,复制的代价太大;

“当无法实现对象复制”----- primer p201;

作为函数的额外信息返回  ;

这时需要采用引用形参

如果使用引用形参的唯一目的是避免复制实参,则应将形参定义为const引用。

因为非const的引用形参 限制了const引用实参的传入;

"int *&v1”----- primer p205

vi是一个引用 用来与指向int型的指针相关联。

容器类型, 通过传递迭代器来处理容器中的元素;数组名会自动转化为第一个元素的指针。数组形参,通常直接定义为指针比使用数组语法定义更好,明确的表示了函数操纵的是指向数组元素的指针。

编译器检查数组形参关联的实参时,只会检查实参是不是指针、指针类型和数组元素是否匹配,不会检查数组长度。

声明为数组引用的形参,编译器不会将实参转化为指针,而是传递数组的引用本身,这种情况下,编译器会检查实参数组大小成为形参数组大小是否匹配。

void b(int (&arr)[10]){...}

&arr左右的括号是必需的,下标具有更高优先级;

b(int &arr[10])==b(int &arr)  ??not sure

多维数组的元素本身就是数组,因此除了第一维以外的所有维的长度都是元素类型的一部分,必须明确指定。

void b(int (*a)[10]); 指向含有10个int型元素的数组的指针。

void b(int a[][10]); 形参是一个指针,指向数组的数组中的元素,数组中的每个元素本身是含有10个int型对象的数组。

7.5.2 传递给函数的数组的处理

确保函数操作不超出数组的边界;

传递数组的第一个元素指针和最后一个元素的下一个位置的指针,就像迭代器一样;

传递数组第一个元素和数组的长度。

7.3 return语句

在循环语句后应提供一个return语句。

main() 没有返回值,编译器会隐式地插入返回0的语句,cstdlib头文件定义了两个预处理变量,分别用于表示程序运行成功和失败。

返回非引用类型时,函数的返回值用于初始化在调用函数处创建的临时对象(temporary object)。

返回引用的函数返回一个左值。

如果不希望引用返回值被修改,返回值应该声明为const;

const char &get_val(...

千万不要返回局部对象的引用。

7.4 函数声明

函数原型 function prototype : 函数返回类型、函数名和形参表。其中,形参表不必对形参命名。

函数应在头文件中声明,在源文件中定义。 定义函数的源文件应包含声明该函数的头文件。

如果一个形参有默认实参,那么它后面的所有形参都必须有默认实参。 默认实参可以是任何适当类型的表达式。

int b(int i1=4,int i2=9,string s1="hi");

int i_func();

string s_func();

b(i_func(), ,s_func());

可以在函数声明,也可以在函数定义里指定默认实参。同一个文件只能为一个形参指定一次默认实参。

下面的例子是错误的

//ff.h

int ff(int=0);

//ff.cc

#include "ff.h"

int ff(int i=0){/*...*/}

通常,在函数声明中指定默认实参,并将该声明放在合适的头文件中。

内联函数应该在头文件中定义。适用于优化小的、只有几行的而且经常被调用的函数。

7.7 类得成员函数

函数原型必须在类中定义。函数体可以在类中也可以在类外定义。

编译器隐式的将类内定义的成员函数当做内联函数。

类成员必须在类定义的花括号内声明;类得成员函数可以访问类得private成员。

this指针

每个成员函数都有一个隐含的形参this,在调用函数时,形参this初始化为调用函数的对象的地址。

《c++ primer》 p223 例子:

bool same_isbn(const Sales_item &rhs) const

{ return isbn==rhs.isbn; }

该函数的调用:

total.same_isbn(trans);

编译器重写为:

Sales_item::same_isbn(&total,trans);

其中,const用来改变this形参的类型,在调用total.same_isbn(trans)时,隐含的this形参将是一个指向total对象的const Sales_Item *类型的指针。

bool Sales_item::same_isbn(const Sales_item *const this, const Sales_item &rhs) const

{ return (this->isbn==rhs.isbn);}

“ const Sales_item *const this  ” 的确切含义应该是指向const对象的const指针,所以该函数不能修改调用该函数的对象。

这种使用const函数叫做常量成员函数(const member function)。

而const对象、指向const对象的指针或者引用只能用来调用const成员函数,尝试调用非const成员函数是错误的。

构造函数与成员函数一样,必须在类中声明,可以在类中或者类外定义。

冒号和花括号之间的代码称为构造函数的初始化列表(constructor initializer list),为类的一个或者多个数据成员指定初值。

每个成员后面是括在圆括号中的初始值。多个成员的初始化用逗号分隔。

Sales_item():units_sold(0),revenue(0.0){ }

编译器创建的默认构造函数通常称为合成的默认构造函数(synthesized default constructor)。

7.7.4 类代码文件的组织

通常将类的声明放在头文件中,类外定义的成员函数置于源文件中。

类定义应置于名为type.h的文件中,类的成员函数定义则一般存储在类同名的源文件中。

7.8 重载函数

两个函数如果具有相同函数名,而形参表不同,则称为重载函数(overloaded function)。

main()函数不能重载。

如果两个函数名、返回类型与形参表都完全相同,则第二个函数声明视为第一个函数的重复声明。

如果两个函数名与形参表都完全相同,但是返回类型不同,则第二个声明是错误的。

函数不能仅基于不同的返回类型实现重载。

void a(int b);

void a(const int b); //重复声明

形参定义为const,并不影响传递至函数的对象; 函数操纵的是实参的副本,形参是否为const无所谓。只有当形参是引用或者指针时,形参是否为const才有影响。 注意,不能基于指针本身是否为const来实现函数的重载。

局部的声明一个函数,则该函数将屏蔽而不是重载在外层作用域中声明的同名函数。 因此,每一个版本的重载函数都应在同一个作用域中声明。

局部声明函数是一种不明智的选择,函数的声明应该放在头文件中。

7.9 指向函数的指针

函数要么用来调用要么用来返回函数指针-------《c++程序设计语言》

函数指针用来指向特定的函数类型,函数类型由返回类型以及形参表确定,而与函数名无关。

bool (*pf)(const string &, const string &); //*pf 两侧的圆括号是必需的;

用typedef简化函数指针的定义

typedef bool (*cmpFcn)(const string &, const string &);

cmpFcn是一种指向函数的指针,它指向的函数“返回bool值 并带有两个const string 引用形参”。

bool lengthCompare(const string &, const string &);

cmpFcn pf1=0;//表示该指针不指向任何函数

pf1=lengthCompare;

pf1=&lengthCompare; // 与上一个同义。

函数的形参可以是指向函数的指针,两种形式:

void useBigger(const string &, const string &, bool(const string &, const string &));

void useBigger(const string &, const string &, bool (*)(const string &, const string &));

返回指向函数的指针

int (*ff(int))(int *, int);

其含义如下:

ff(int )为函数 该函数返回指向 int(*)(int *, int)指针。

typedef int (*PF)(int *, int);

PF ff(int);// ff返回PF指针。

形参允许定义为函数类型,函数的返回类型则必须为指向函数的指针。

具有函数类型的形参所对应的实参将被自动转换为指向该函数类型的指针。

C++允许函数指针指向重载函数,指针类型必须与重载函数精确匹配,包括形参和返回类型。

原文地址:https://www.cnblogs.com/nimo299/p/2044178.html