回顾 C++的指针函数 函数指针

作者:雨辰 发布于:2016-4-5 10:45 Tuesday 分类:C/C++

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.
0045F688
Desconstruct.
0045F788 10 请按任意键继续. . .

   可以看到,在"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.
00754AA8
00754AA8 10 请按任意键继续. . .

   可以看出,在函数"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

标签: C++

发表评论:

雨辰 joyimp|@2011-2018 京ICP备16030765号