C++ primer(七)--函数、C++的编程模块 函数指针 函数指针数组 typedef
2013-10-07 15:22
519 查看
如何定义函数、给函数传递信息以及从函数那里获得信息。如何使用函数来处理数组、字符串和结构,最后介绍递归和函数指针。
一、函数的基础
对于有返回值的函数,必须使用返回语句,C++对于返回值的类型有一定的限制:不能是数组,可以是其他任何类型--甚至是结构体和对象!(虽说不能直接返回数组,但是可以将数组作为结构或对象组成部分来返回)。
在原型的参数列表中,可以包括变量名,也可以不包括。
二、按值传递
C++通常按值传递参数,这意味着将数值参数传递给函数,而后者将其赋给一个新的变量。
1)const和指针
声明一个指向常量的指针pt;
int age=39;
const int *pt=&age;
该声明指出,pt指向一个const int(这里是39),因此不能使用pt来修饰这个值。换句话说,*pt的值为const,不能被修改:
*pt+=1;// error
cin>>*pt;// error
pt的声明并不意味着它指向的值实际上就是一个常量,而只是意味着对pt而言,这个值是常量。例如,pt指向age,而age不是const。可以直接通过age变量修改age的值,但不能使用pt指针来修改它:
*pt=20;//error
age=20;//no error
这种声明中的const只能防止修改pt指向的值(这里是39),而不能防止修改pt的值。也就是说,可以将一个新地址赋给pt:
int sage=80;
pt=&sage; //no error
但仍然不能使用pt来修改它指向的值(现在为80)。
这里将常规变量的地址赋给指向const的指针。因此还有两种可能:一个是将const变量的地址赋给指向const的指针、将const的地址赋给常规指针。第二种可行,第一种不可行。
const int gp=10;
const int *pe=&gp; // no error
const int gm=21;
int * pm=&gm; // error
对于这种情况来说,既不能使用gp来修改值10,也不能使用pe来修改。对于第二种情况,C++禁止将const的地址赋给非const指针。
假设有一个由const数据组成的数组:
const int months[];
对于函数定义:int sum(int arr[],int n);
int j=sum(months,12);//error 编译器不允许这样
三、函数指针
1)使用指针来调用函数
对于函数指针的声明和初始化在此省略:
double pam(int);
double (*pf)(int);
pf=pam;
double x=pam(4);
double y=(*pf)(5);
实际上,C++也允许像使用函数名那样使用pf:
double y=pf(5);
也就是说pf和(*pf)等价,也就是说对于函数指针来调用函数,可以通过两种方式来实现,一个是直接使用函数指针,也就是第二种方式;另一种就是使用函数指针来构造和函数名一样的那样来调用,也就是第一种方式。
2)深入探讨函数指针
这里主要讨论函数指针数组。比如三个函数:
const double * f1(const double ar[],int n);
[b]const double * f2(const double [],int );[/b]
[b]const double * f1(const double *,int );[/b]
[b] 如果有一个函数指针数组将很方便。这种声明类似于当个函数指针的声明,但必须在某个地方加上[3],以指出这是一个包含三个函数指针的数组:[/b]
[b] const double * (*pa[3])(const doble *,int)={f1,f2,f3};[/b]
[b] pa是一个包含三个元素的数组,而要声明这样的数组,首先需要使用pa[3],该声明的其他部分指出了数组包含的元素是什么样的。运算符[]的优先级高于*,因此*pa[3]表明pa是一个包含三个指针的数组。此时可以调用函数如下所示:[/b]
[b] const double * px=pa[0](av,3);[/b]
[b] const double * py=(*pa[2])(av,3);// 依然是两种方式在调用函数[/b]
[b] 可以创建一个指向真个数组的指针,由于数组名pa是指向函数指针的指针,因此指向数组的指针将是这样的指针,既它指向指针的指针。这种声明类似于pa的声明,但由于增加了一层间接,因此需要在某个地方添加一个*。具体地说,如果这个指针名为pd,则需要指出它是一个指针,而不是数组。这意味着声明的核心部分是(*pd)[3],其中的括号让标示符pd与*先结合,也就是数组指针和指针数组的区别,pd是一个指针,它指向一个包含三个元素的数组。[/b]
[b] const double *(*(*pd)[3])(const double *,int)=&pa;[/b]
[b] 要调用函数,需要认识到这样一点:既然pd指向数组,那么*pd就是数组,而(*pd)[i]是数组中的元素,既函数指针。因此,较简单的函数调用是(*pd)[i](av,3),而*(*pd)[i](av,3)是返回的指针指向的值。也可以使用第二种使用指针调用函数的语法:使用(*(*pd)[i])(av,3)来调用函数,而*(*(*pd)[i])(av,3)是指向的double值。[/b]
[b] 请注意pa(它是数组名,表示地址)和&pa之间的区别。pd是数组第一个元素的地址,既&pa[0]。因此,他是单个指针的地址。但&pa是整个数组(既三个指针块)的地址。从数字上说,pa和&pa的值相同,但他们的类型不同。(类型不同,在《C专家编程》中有那么一章单独说明这个问题)。一种差别是,pa+1为数组中下一个元素的地址,而&pa+1为数组pa后备一个12字节内存块的地址,另一个差别是,要得到第一个元素的值,只需对pa解除一次饮用,但需要对&pa解除两次引用:[/b]
[b] **&pa==*pa==pa[0];[/b]
[b]四、使用typedef[/b]
[b] 使用这个关键字创建类型别名:[/b]
[b] typedef const double * (*p_fun)(const doble *,int); //p_fun 现在是一种新的类型[/b]
[b] p_fun p1=f1;[/b]
[b] 然后使用这个别名来简化代码:[/b]
[b] p_fun pa[3]={f1,f2,f3};[/b]
[b] p_fun (*pd)[3]=&pa;[/b]
[b] 对于这个很严肃的问题,还是用代码说明比较好,这段代码在书中也有相似的:[/b]
一、函数的基础
对于有返回值的函数,必须使用返回语句,C++对于返回值的类型有一定的限制:不能是数组,可以是其他任何类型--甚至是结构体和对象!(虽说不能直接返回数组,但是可以将数组作为结构或对象组成部分来返回)。
在原型的参数列表中,可以包括变量名,也可以不包括。
二、按值传递
C++通常按值传递参数,这意味着将数值参数传递给函数,而后者将其赋给一个新的变量。
1)const和指针
声明一个指向常量的指针pt;
int age=39;
const int *pt=&age;
该声明指出,pt指向一个const int(这里是39),因此不能使用pt来修饰这个值。换句话说,*pt的值为const,不能被修改:
*pt+=1;// error
cin>>*pt;// error
pt的声明并不意味着它指向的值实际上就是一个常量,而只是意味着对pt而言,这个值是常量。例如,pt指向age,而age不是const。可以直接通过age变量修改age的值,但不能使用pt指针来修改它:
*pt=20;//error
age=20;//no error
这种声明中的const只能防止修改pt指向的值(这里是39),而不能防止修改pt的值。也就是说,可以将一个新地址赋给pt:
int sage=80;
pt=&sage; //no error
但仍然不能使用pt来修改它指向的值(现在为80)。
这里将常规变量的地址赋给指向const的指针。因此还有两种可能:一个是将const变量的地址赋给指向const的指针、将const的地址赋给常规指针。第二种可行,第一种不可行。
const int gp=10;
const int *pe=&gp; // no error
const int gm=21;
int * pm=&gm; // error
对于这种情况来说,既不能使用gp来修改值10,也不能使用pe来修改。对于第二种情况,C++禁止将const的地址赋给非const指针。
假设有一个由const数据组成的数组:
const int months[];
对于函数定义:int sum(int arr[],int n);
int j=sum(months,12);//error 编译器不允许这样
三、函数指针
1)使用指针来调用函数
对于函数指针的声明和初始化在此省略:
double pam(int);
double (*pf)(int);
pf=pam;
double x=pam(4);
double y=(*pf)(5);
实际上,C++也允许像使用函数名那样使用pf:
double y=pf(5);
也就是说pf和(*pf)等价,也就是说对于函数指针来调用函数,可以通过两种方式来实现,一个是直接使用函数指针,也就是第二种方式;另一种就是使用函数指针来构造和函数名一样的那样来调用,也就是第一种方式。
2)深入探讨函数指针
这里主要讨论函数指针数组。比如三个函数:
const double * f1(const double ar[],int n);
[b]const double * f2(const double [],int );[/b]
[b]const double * f1(const double *,int );[/b]
[b] 如果有一个函数指针数组将很方便。这种声明类似于当个函数指针的声明,但必须在某个地方加上[3],以指出这是一个包含三个函数指针的数组:[/b]
[b] const double * (*pa[3])(const doble *,int)={f1,f2,f3};[/b]
[b] pa是一个包含三个元素的数组,而要声明这样的数组,首先需要使用pa[3],该声明的其他部分指出了数组包含的元素是什么样的。运算符[]的优先级高于*,因此*pa[3]表明pa是一个包含三个指针的数组。此时可以调用函数如下所示:[/b]
[b] const double * px=pa[0](av,3);[/b]
[b] const double * py=(*pa[2])(av,3);// 依然是两种方式在调用函数[/b]
[b] 可以创建一个指向真个数组的指针,由于数组名pa是指向函数指针的指针,因此指向数组的指针将是这样的指针,既它指向指针的指针。这种声明类似于pa的声明,但由于增加了一层间接,因此需要在某个地方添加一个*。具体地说,如果这个指针名为pd,则需要指出它是一个指针,而不是数组。这意味着声明的核心部分是(*pd)[3],其中的括号让标示符pd与*先结合,也就是数组指针和指针数组的区别,pd是一个指针,它指向一个包含三个元素的数组。[/b]
[b] const double *(*(*pd)[3])(const double *,int)=&pa;[/b]
[b] 要调用函数,需要认识到这样一点:既然pd指向数组,那么*pd就是数组,而(*pd)[i]是数组中的元素,既函数指针。因此,较简单的函数调用是(*pd)[i](av,3),而*(*pd)[i](av,3)是返回的指针指向的值。也可以使用第二种使用指针调用函数的语法:使用(*(*pd)[i])(av,3)来调用函数,而*(*(*pd)[i])(av,3)是指向的double值。[/b]
[b] 请注意pa(它是数组名,表示地址)和&pa之间的区别。pd是数组第一个元素的地址,既&pa[0]。因此,他是单个指针的地址。但&pa是整个数组(既三个指针块)的地址。从数字上说,pa和&pa的值相同,但他们的类型不同。(类型不同,在《C专家编程》中有那么一章单独说明这个问题)。一种差别是,pa+1为数组中下一个元素的地址,而&pa+1为数组pa后备一个12字节内存块的地址,另一个差别是,要得到第一个元素的值,只需对pa解除一次饮用,但需要对&pa解除两次引用:[/b]
[b] **&pa==*pa==pa[0];[/b]
[b]四、使用typedef[/b]
[b] 使用这个关键字创建类型别名:[/b]
[b] typedef const double * (*p_fun)(const doble *,int); //p_fun 现在是一种新的类型[/b]
[b] p_fun p1=f1;[/b]
[b] 然后使用这个别名来简化代码:[/b]
[b] p_fun pa[3]={f1,f2,f3};[/b]
[b] p_fun (*pd)[3]=&pa;[/b]
[b] 对于这个很严肃的问题,还是用代码说明比较好,这段代码在书中也有相似的:[/b]
#include <iostream> const int * f1(const int ar[],int n); const int * f2(const int [],int ); const int * f3(const int *,int); using namespace std; int main() { int temp[]={2,3,4}; int i; cout<<"单个函数指针"<<endl; const int * (*p1)(const int *,int n)=f1; const int * mn=p1(temp,3); cout<<(*p1)(temp,3)<<": "<<*(*p1)(temp,3)<<endl; cout<<p1(temp,3)<<": "<<*(*p1)(temp,3)<<endl; cout<<mn<<": "<<mn[0]<<endl; cout<<temp<<endl; cout<<"函数指针数组 两种方法"<<endl; const int * (*pa[3])(const int *,int n)={f1,f2,f3}; for(i=0;i<3;i++) cout<<pa[i](temp,3)<<": "<<*(pa[i])(temp,3)<<endl; for(i=0;i<3;i++) cout<<(*pa[i])(temp,3)<<": "<<*(*pa[i])(temp,3)<<endl; cout<<"二级指针"<<endl; const int * (**pb)(const int *,int n)=pa; for(i=0;i<3;i++) cout<<pb[i](temp,3)<<": "<<*pb[i](temp,3)<<endl; for(i=0;i<3;i++) cout<<(*pb[i])(temp,3)<<": "<<*(*pb[i])(temp,3)<<endl; cout<<"指针地址"<<endl; const int * (*(*pc)[3])(const int *,int n)=&pa; for(i=0;i<3;i++) cout<<(*pc)[i](temp,3)<<": "<<*(*pc)[i](temp,3)<<endl; for(i=0;i<3;i++) cout<<(*(*pc)[i])(temp,3)<<": "<<*(*(*pc)[i])(temp,3)<<endl; return 0; } const int * f1(const int ar[],int n) { return ar; } const int * f2(const int ar[],int n) { return ar+1; } const int * f3(const int ar[],int n) { return ar+2; }
相关文章推荐
- [c++] 函数指针和函数指针数组的使用方法
- 【C++ primer】第七章 函数-C++的编程模块
- C++引用数组,函数指针,函数指针数组,结构体数组等学习
- 【C++ primer】第七章 函数-C++的编程模块
- 【C++ primer】第七章 函数-C++的编程模块
- 【C++ primer】第七章 函数-C++的编程模块
- C/C++ 一段代码区分数组指针|指针数组|函数指针|函数指针数组
- 关于函数指针数组与返回数组指针的函数
- c/c++ 函数、常量、指针和数组的关系梳理
- C++指针和数组:数组指针应用,函数指针
- 一劳永逸:关于C/C++中指针、数组与函数复合定义形式的直观解释
- 理解复杂的C/C++声明 const, typedef , 函数指针
- c++ 函数 数组 传参 指针下标
- 关于C++中函数指针的使用(包含对typedef用法的讨论)
- 函数指针与函数指针数组的使用方法
- c++ primer 第五版学习笔记-第6章-返回数组指针的函数和函数指针的数组
- C++中的指针、数组指针与指针数组、函数指针与指针函数
- C++ primer 读书笔记系列——(3)C++中的数组和指针
- 变量、指针变量、指针数组、数组指针、函数指针、函数指针数组
- 指针数组、数组指针、函数指针、函数指针数组、指向函数指针数组的指针的理解