C++ Primer(函数)
来源:互联网 发布:专业网络直播设备 编辑:程序博客网 时间:2024/06/05 17:13
第七章 函数
7.1函数的定义
递归求公约数
int regcd(int v1,int v2)
{if(v2!=0)
return regcd(v2,v1%v2);
return v1;
}
形参是在函数的形参表中定义的,并由调用函数时传递给函数的实参初始化。
形参是一个表达式,可以是变量或字面值常量,包含一个或几个操作符的表达式。
7.1.1 函数的返回类型可以是内置类型(如int或double)、类类型或复合类型(如int&或string*),还可以是void类型,表示该函数不返回任何值。
函数必须指定返回类型。
7.1.2函数形参表可以为空,但不能省略。如果两个参数具有相同的类型,必须重复声明。
int manip(int v1,int v2);
7.2参数传递
7.2.1 非引用形参
普通的非引用形参通过复制对应的实参实现初始化。
- 可以将指向const对象的指针初始化为非const对象,但不可以让指向非const对象的指针指向const对象。
- 函数使用非引用的非const形参,既可以给该函数传递const实参也可传递非const的实参。
- 不适宜赋值实参的情况:需要在函数总修改实参的值时;需要以大型对象作为实参传递时;没有办法实现对象的复制时。
7.2.2 引用形参
void swap(int &v1,int &v2)
{
int temp=v2; v2=v1; v1=temp;
}
引用形参直接关联到其所绑定的对象。
1.向主函数返回额外的结果
vector<int>::const_iterator find_val(vector<int>::const_iterator beg,
vector<int>::const_iterator end,
int value,vector<int>::size_type occurs)
{
vector<int>::const_iterator res_iter=end;
occurs=0;
for(;beg!=end;++end)
if(*beg==value){
if(res_iter==end)
res_iter=beg;
++occurs;
}
return res_iter;
}
2.利用const引用避免复制
string对象相当长时
bool isShorter(const string &s1;const string &s2)
{ return s1.size()>s2.size();}
3.将不需要修改的引用形参定义为const引用。
4.传递指向指针的应用
void ptrswap(int *v1,int *v2) //v1是一个引用,与指向int型对象的指针相关联。
7.2.3通常函数不应该有vector或其他容器类型的形参,传递迭代器就可以了
7.2.4数组形参
1.由于不能复制数组,所以无法编写使用数组类型形参的函数。数组可以自动转化成指针 ,所以通常通过操纵指向数组中的元素的指针来处理数组。
以下三个等价:都看作是指向数组元素的指针
void fun(int*)// 最好
void fun(int[]) // ok
void fun(int[10])
2.编译器检查数组形参关联的实参是,只会检查实参是不是指针、指针的类型和数组元素的类型是否匹配,不会检查数组的长度。3.数组实参
数组实参若以非引用形式传递,则会悄悄的转成指针,非引用类型的形参会初始化为相应的的副本,实参是第一个元素的地址,而形参复制的是这个地址的副本,操作的是这个副本,所以不会修改实参指针的值,但是可以修改它们共同指向的对象内容。
所以,数组非引用实参是指针的值传递!
如果不修改数组元素(保护数组)时,那么应该定义为指向const对象的指针
void fun(const int*)
4.数组引用形参
void printValues(int (&arr)[10]) { ...... } // 括号是必须的
这个时候,数组实参不会转成指针了,而是传递数组引用本身
必须写大小,实参的大小必须与10匹配
5.多维数组的传递
void printValues(int (*matrix)[23], int rowSize) { .... } void printValues(int matrix[][23], introwSize); // 实际上是指针
7.3return语句7.3.1不带返回值的return语句只能用于返回类型为void的函数。
7.3.2返回类型不是void的函数必须返回一个值,而且这个返回值的类型必须和函数的返回类型相同,或者能隐式转化为函数的返回类型。
1.非void函数必须返回的特殊情况,main函数最后的reutn 0不是必须的
main函数不能递归,不能调用自身
main函数不能重载
2.返回非引用类型在调用函数的地方会将函数返回值复制给临时对象。
3.函数返回引用类型时返回的是对象本身。
4.千万不可返回局部对象的引用,也不能返回局部对象的指针。
7.4函数声明
变量和函数都声明在头文件中,定义在源文件中
源文件包含声明函数的头文件,进行匹配检查
声明在头文件中的好处是确保在所有文件中声明一致,修改方便
1.默认实参,:如果有一个形参有默认实参,那么它后面的所有形参都要有使用最频繁使用的排在最后
默认实参可以是表达式或有返回值的函数调用
在头文件中声明默认实参
7.5局部对象
1.自动对象
只有当定义它的函数调用时才存在的对象
一般指形参和局部变量,它们在定义它们的语句块结束时撤销
2.静态局部对象
一个变量定义在函数的作用域内,但生命周期跨越了这个函数多次调用,这样的对象定义为static。
输出1--20
size_t count() {
static size_t c = 0;
return++c;
}
int main() {
for(size_t ix = 0; ix != 20; ++ix) {
cout<< count() << “ ”;
}
return 0;
}
7.6内联函数
内联函数在程序的每个调用点上“内联的”展开。
内联机制适用于优化小的、只有几行的而且经常被调用的函数。应该在头文件中定义。
7.7类的成员函数
1.每个成员函数都有一个this形参,是调用该函数的对象的地址
对象实例调用自己的成员函数,将自己传给这个成员函数与之进行绑定
this指针是隐含的,不能明式出现在形参表中
2.常成员函数bool same_isbn(constSales_item&)const;total.same_isbn(trans);调用时,则这个this是指向total的const Sales_item*类型的指针, 是个指向const对象的指针,所以这个函数不能改变数据成员
const对象、指向const对象的指针或引用只能用于调用其const成员函数!!反过来,非const的这帮东西可以调用const的成员函数(并非必须是const的对象才能调用)
换句话:const对象不能调用非const成员函数
对于成员函数,声明与定义必须一致,如果要const那么两者都要同时有const
3.类外定义的成员函数的声明必须与其定义一致。4.构造函数与类同名,而且没有返回类型。一个类可以有多个构造函数,但必须有不同的数目或类型的形参。
5.构造函数的初始化列表在构造函数的形参表之后,以冒号开头,一系列的成员名和圆括号中的初始值,用逗号隔开。
7.8函数重载
名字相同而形参表不同
函数返回类型,最右边形参具有默认实参,以及const的非引用形参不能作为重载的区别标志
int fuc1(int*);
int fuc1(const int*); //重复声明 ,没有error
f(int*)
f(const int*)// 可以重载
而下面的
f(int*)
f(int*const) //不能重载(值传递,副本传递) // 这里是const指针,只有指向const对象的指针作形参才能实现重载
再补充:仅当形参是引用或指针时,形参是否为const才有影响
7.8.3重载的三个步骤候选函数
选择可行函数
寻找最佳匹配
7.9指向函数的指针
函数指针:bool (*pf)(int); //指向函数的指针
而指针函数:bool *pf(int); // 返回值是指向bool指针
使用typedef简化函数指针
typedefbool (*pf)(int); //pf是一个种指向函数的指针的名字,它所指向的函数有一个int参数,返回值是bool类型
函数指针的初始化和赋值: (三种,0、函数名、&函数名)
第一种:pf fuc1 = 0;
//等于bool (*fuc1)(int)= 0; // 蓝色部分就是类型
第二种:使用函数名
注意:bool setAge(int); 其中setAge除了用于函数调用外,其他任何使用都将解释为指针: bool(*)(int);
pf fuc2 = setAge; // 使用函数名进行初始化
fuc1 = fuc2; //或赋值
上面直接使用函数名setAge等于在函数名上取地址操作
pffuc2 = setAge;
pffuc2 = &setAge; // 两个等价
而使用 pf fuc3(3); // 直接初始化是错的
指向不同类型函数的指针不存在转换
可以通过函数指针调用函数
fuc2 = setAge;
调用:fuc2(32); // 前提是这个函数指针已经初始化,若是0或未初始化不行
函数指针作形参
voidsamplefuction(const string&, bool(int));
//函数类型的形参,对应实参将被自动转换为相应的函数指针
voidsamplefuction(const string&, bool (*)(int));
//函数指针类型的形参,与上面声明等价
返回类型是指向函数的指针(返回类型可以是函数指针类型,但不可以是函数类型) 后补充:函数ff的返回类型是一个指向”外围”函数的指针
bool (*ff(int))(int*, int) // 蓝色部分是类型 这句话用在这里是在声明ff这个函数
ff(int)函数返回一个函数指针,它的类型是bool (*)(int*, int)
使用typedef使用该定义更加简明易懂
typedefbool (*PF)(int*, int)
PFff(int); // 声明ff这个函数
举例:
typedef int func(int*, int);
void f1(func); // ok,函数类型可以作形参,对应实参将自动转成函数指针
func f2(int); // error!! 返回类型不能是函数类型,不能自动转成函数指针
func *f3(int); // ok, 返回类型是函数指针
指向重载函数的指针
必须精确匹配
extern void ff(double);
extern void ff(int); // ok,重载
void (*pf)(double)= &ff; // ok, 精确匹配,对应第一个
int(*pf)(double) = &ff; // error, 返回值不匹配
- C++Primer学习笔记(7)函数
- C++primer(十三) 拷贝函数(续)
- 《C++Primer》读书笔记(六)函数
- C++Primer 函数
- C++primer函数进阶
- 【c++primer】函数探幽
- c++Primer,七,函数
- c++primer 要点-函数
- C++primer 函数
- C++primer函数汇总
- c++primer 3/1 ---函数
- 重载函数 (C++Primer-9)
- 《C++Primer》读书笔记--函数模板
- c++primer之函数重载
- C Primer Plus(九) 函数
- 指向函数的指针(自C++Primer )
- C primer plus第9章(函数)习题
- C++primer(第五版)第六章函数学习笔记
- 第十七周项目二:引用做形参:传地址值
- poj1804(归并排序求逆序数)
- 第十七周项目1-体会函数参数传递
- 17周项目3--胖子伤不起
- 解决Android SDK Manager更新、下载速度慢
- C++ Primer(函数)
- Search in Rotated Sorted Array II -- Leetcode
- Git 常用命令
- 第17周【项目 6-学生成绩统计】(5)
- 【java】接口的应用的一个小例子
- 第17周项目3-胖子伤不起(结构体类型)
- 磁盘不能自动mount上来的solution(solution for nfs disks can't be mounted automatically)
- 一个标准的helloworld程序(java)
- 第17周项目4-生日相差几天