[C++基础] 指针函数与函数指针<详细讲解>

来源:互联网 发布:star法则简历模板java 编辑:程序博客网 时间:2024/04/30 23:24

1. 前言

   关于指针函数和函数指针,特别是函数指针,相信很多C/C++ers跟我曾经一样,对它抱有敬畏,认为它是很高深的东西,其实不然。要理解它花不了多少功夫,或许我一句话就能说清楚二者的区别,但是这样也只是在脑子里形成一个概念而已。大学时代,作为一名学生时,我可以一天看完毛概,考八九十分;但是我用了一个星期去看谭浩强的C++教材(尽管现在很多人鄙视这本教材),上机时却仍无从下手,我可以侃侃而谈,熟悉一切概念,但是就是编不出程序。这就是程序员的世界,凡事只有动手才能领悟真谛。不过这也应证了一句千古名句,也是我最喜欢的一句诗“纸上得来终觉浅,绝知此事要躬行”。

   本文所有代码编译及运行环境:windows 7 professionnal, Visual Studio2010 professional.

2. 概述

   按照行文的总-分-总的结构,这里仍然先概括的介绍一下指针函数和函数指针的概念,然后再用程序来详细的介绍二者。下面就是指针函数和函数指针的概念。

  【指针函数】:返回指针的函数。重点是它是一个函数,只是返回值由普通的值或对象变成了指针,也就是说这个函数返回的是一块内存的地址。

  【函数指针】:指向函数的指针。重点是它是一个指针,只是它指向的内容由普通的变量或对象变成了函数,也就是说它可以指向函数的入口地址。

3. 指针函数

   在介绍指针函数之前,我们先来看一个普通的函数。

复制代码
 1 #include <iostream> 2 using namespace std; 3  4 class MyType{ 5 public: 6     MyType(int value):m_value(value){ 7         cout<<"Construct."<<endl; 8     } 9     ~MyType(){10         cout<<"Desconstruct."<<endl;11     }12 public:13     int m_value;14 };15 16 MyType getInstanceOfMyType(){17     MyType mt(10);18     cout<<&mt<<endl;19     return mt;20 }21 22 int main(){23 24     MyType mt = getInstanceOfMyType();25     cout<<&mt<<endl;26     cout<<mt.m_value<<endl;27 28     system("pause");29     return 0;30 }
复制代码

   涂色部分就是我们需要注意的地方,函数"getInstanceOfMyType()"内部创建了一个MyType的对象,接着输出了该对象的地址,最后返回了该对象。main函数里面,通过调用该函数,获得了函数的返回值,接着打印了返回对象的地址,再输出获得对象的m_value属性的值。输出结果如下:

Construct.0045F688Desconstruct.0045F78810请按任意键继续. . .

   可以看到,在"getInstanceOfMyType()"函数里,对象创建之后又被销毁了。从输出可以看出,返回的对象地址与函数里创建的对象地址是不一样的,但是属性m_value的值是一样的,这说明通过该普通函数获取的是函数内部创建对象的一个副本,这就是普通函数在返回对象时的处理。

   在看到普通函数的处理之后,我们再来看一个指针函数的处理,下面是一段指针函数的代码,注意,这段代码与上一段很相似,要注意区分。

复制代码
 1 #include <iostream> 2 using namespace std; 3  4 class MyType{ 5 public: 6     MyType(int value):m_value(value){ 7         cout<<"Construct."<<endl; 8     } 9     ~MyType(){10         cout<<"Desconstruct."<<endl;11     }12 public:13     int m_value;14 };15 16 MyType *getInstanceOfMyType(){17     MyType *mt = new MyType(10);18     cout<<mt<<endl;19     return mt;20 }21 22 int main(){23 24     MyType *mt = getInstanceOfMyType();25     cout<<mt<<endl;26     cout<<mt->m_value<<endl;27 28     system("pause");29     return 0;30 }
复制代码

   上面代码着色的部分需要我们注意,特别是函数"getInstanceOfMyType()",它在这里已经是一个指针函数了,那么,这段程序的输出是什么呢?如下:

Construct.00754AA800754AA810请按任意键继续. . .

   可以看出,在函数"getInstanceOfMyType()"中的对象一直没有被调用析构函数,函数内和函数外的对象的地址是完全一样的,当然,对象里存储的内容m_value的值也是一样的。你可能会问,不是说函数调用完,就销毁局部变量吗?是的,它销毁了,但是它只销毁了"MyType *mt"这个指针,它指向的内存却不会被销毁。所以,在外面我们仍然可以继续访问这个对象。这种情况下,我们一般是需要在函数调用外面加上我们自己的delete操作的,上面的程序没有添加这样的操作,严格上来讲是一个错误的程序。

   使用指针函数时,直接返回函数内部对象的地址,这样就无需重新制造对象的副本,对效率的提升有帮助。但是需要注意的是,一定要记得在函数外部将函数内部申请的内存释放掉,否则就有内存溢出的风险。

4. 函数指针

   下面说道我们今天主要的话题了——函数指针。函数指针是一个很有用的技术,它使得我们可以通过指针就能执行某一个函数代码。对于技术高超的人来说,它是一把【绝世好剑】,能够解决很多问题。下面,我们就函数指针来探究一番。

   首先,来看一段最简单的函数指针的代码,注意声明和调用的方式。

复制代码
 1 #include <iostream> 2 using namespace std; 3  4 int printFunc(int value){ 5     cout<<"this is a print function. the value is:"<<value<<endl; 6     return 0; 7 } 8  9 int main(){10 11     int (*pFunction)(int x); // 这是一个函数指针变量12     pFunction = printFunc;   // 这里将函数入口地址给函数指针13     (*pFunction)(7);         // 通过*运算符获取了函数,再传入参数7执行了函数14 15     system("pause");16     return 0;17 }
复制代码

   上述代码着色部分就是函数指针的声明-定义-执行的过程,可以看出来,我只要将函数入口地址给函数指针就可以执行函数了。这里有个知识点,就是关于函数的调用方式,一般我们调用函数的方式是这样的:函数名(参数列表),但是其实函数的调用方式也可以这样来写:(*函数名)(参数列表)。即可以如下来调用函数,只是很少这样用:

1 (*printFunc)(8);

   除此之外,我们还可以这样写:(&函数名)(参数列表)。即如下调用函数,这也几乎没人这样用:

1 (&printFunc)(8);

   对于函数指针,它有两个前提:①.就是指向的函数返回值要与声明的函数指针一致。②.指向的函数的参数类型及个数要与声明的函数指针一致。否则,是无法编译通过的。

5. 函数指针类型

   上面一节在使用函数指针的时候,直接声明了一个函数指针。其实函数指针也可以借助typedef声明为一个类型,这样我们就可以像定义int型变量一样来定义一个函数指针了。定义函数指针类型代码如下:

复制代码
 1 #include <iostream> 2 using namespace std; 3  4 int printFunc(int value){ 5     cout<<"this is a print function. the value is:"<<value<<endl; 6     return 0; 7 } 8 typedef int (*PFunction)(int x); // 函数指针类型,注意返回值和参数列表 9 10 int main(){11 12     PFunction ptrFunc; // 定义函数指针变量13     ptrFunc = printFunc;14     (*ptrFunc)(1); // 第一种调用方式15     ptrFunc(2);    // 第二种调用方式16 17     system("pause");18     return 0;19 }
复制代码

6. 一个函数指针的妙用示例

复制代码
 1 #include <iostream> 2 using namespace std; 3  4 typedef void (*PFunction)(int x); // 函数指针类型,注意返回值和参数列表 5  6 void printA(int value){ 7     cout<<"A - "<<value<<endl; 8 } 9 10 void printB(int value){11     cout<<"B - "<<value<<endl;12 }13 14 void printC(int value){15     cout<<"C - "<<value<<endl;16 }17 18 int main(){19     int choice;20     PFunction ptrFunc[3] = {printA, printB, printC};21     cin>>choice;22     ptrFunc[choice](choice);23 24     system("pause");25     return 0;26 }
复制代码

   具体的这里就不解说了,代码很短,也很容易看懂。

7. 结语

   本文就指针函数和函数指针做了一个简单的入门讲解,希望读者在阅读完本文以后,对指针函数和函数指针有一个深入的认识。当然,写作本文的目的也是为了强化笔者的C++基础功底。



http://www.cnblogs.com/alephsoul-alephsoul/archive/2012/10/19/2730337.html

0 0
原创粉丝点击