C++ Basic 系列文章目录
C++ Basic 31 : 函数指针与指针函数
C++ Basic 30 : 箭头-> 双冒号:: 点号.操作符区别
C++ Basic 29 : 接口(抽象类)
....
C/C++语言的内存四区(栈区,堆区,全局区,代码区)(附图详解)
前言
在学习C++面向对象的编程语言过程中发现“指针函数”与“函数指针”容易搞错,所以今天,我自己想一次把它搞清楚。
一、指针函数
指针函数定义:
指针函数时指带指针的函数,简单来讲,其本质是一个函数,函数的返回类型是某一类指针,
声明格式: 类型标识符 * 函数名(参数表)
int * func (int , int)
对比普通函数声明格式: 类型标识符 函数名(参数表),
int func (int , int )
这种函数的声明应该非常熟悉,函数func()形参传入两个int型参数,返回值也是int类型数值。反观指针函数,它和普通函数的最大区别是函数名前面多了一个*,而这个函数就是指针函数。其返回值是一个地址,而地址一般为4字节int整型。
便于理解,可以将指针函数做如下描述:函数func()是一个指针(pointer )指向(*)int 类型的地址。
1. 这样描述应该很容易理解了,所谓的指针函数也没什么特别的,和普通函数对比不过就是其返回了一个指针(即地址值)而已。
2. 函数返回值必须用同类型的指针变量来接受,也就是说,指针函数一定有函数返回值,而且,在主调函数中,函数返回值必须赋给同类型的指针变量。
指针函数的写法:
int *fun(int x,int y); //指针函数
int * fun(int x,int y);
int* fun(int x,int y); //推荐写法
int* fun_ptr = NULL; //声明同类型的空指针,用于接收指针函数返回的地址
fun_ptr = fun(x,y); // 将指针函数的返回值,即地址值,赋给指针变量fun_ptr
这个写法看个人习惯,其实如果*靠近返回值类型的话可能更容易理解其定义。
示例:
#include <iostream>
#include "Area.h"
#include <fstream>
using namespace std;
// 函数指针
template <typename elemsType>
elemsType* add_xy(const elemsType x, const elemsType y) {
elemsType* ptr = new elemsType;
*ptr = x + y;
/* Information output to iostream */
cout << " add_xy() : x+y= "
<< *ptr << "\t ptr address: "
<< ptr << endl;
return ptr;
}
int main()
{
AreaClass cirArea; // class AreaClass
int R = 1;
int* fun_ptr = NULL; // NULL ptr pointer to funtion
fun_ptr = add_xy(R, R);
cout << "fun_ptr address :\t"
<< &fun_ptr << '\t'
<< "fun_ptr content : \t"
<< fun_ptr << '\t'
<< "fun_ptr address value : \t"
<< *fun_ptr
<< endl;
delete fun_ptr;
bool is_get_rads = false;
is_get_rads = cirArea.getRadius(R);
if (is_get_rads != true) {
cerr << "Error: is_get_rads != true " << endl;
return -1;
}
double cir_area = cirArea.getArea();
ofstream outStream("AreaClassDataFile.txt",
ios::app); //以追加的形式写入到文件中
if (!outStream) { //empty or error
cerr << "Error Opening Input File Stream" << endl;
}
std::cout << "cirArea.getArea( R ):\t"
<< R
<< '\t'
<< cir_area
<< endl; //输出到标准输入输出流
outStream << "cirArea.getArea( R ):\t"
<< R
<< '\t'
<< cir_area
<< endl; //输出到文件流outStream中去
outStream.close(); //关闭文件
return 0;
}
结果:
分析:指针函数计算加法结果,将存储结果的地址返回;主调函数调用指针函数,接收其返回的地址值并赋给一个同类型的指针变量。
注意:在调用指针函数时,需要一个同类型的指针来接收其函数的返回值。主调函数传入参数为int类型,指针函数模板函数会完成类型选择即为int类型,因此,指针函数的返回类型也应为int类型。接收指针函数返回值得指针变量类型也应该是int类型。
二、函数指针
函数指针,其本质是一个指针变量,该指针指向这个函数。总结来说,函数指针就是指向函数的指针。
指向函数的指针包含了函数的地址,可以通过它来调用函数。声明格式如下:
类型说明符 (*函数名)(参数)
int (*fptr)(int x,int y); /* 声明一个函数指针 */
指针名和指针运算符外面的括号改变了默认的运算符优先级。如果没有圆括号,就变成了一个返回整型指针的函数的原型声明。
函数指针是需要把一个函数的地址赋值给它,有两种写法:
fptr = &Function; /* 将Function函数的首地址赋给指针fptr */
fptr = Function;
可以采用如下两种方式来通过指针调用函数:
x=(*fptr)();
x=fptr();
第二种格式看上去和函数调用无异。但是有些程序员倾向于使用第一种格式,因为它明确指出是通过指针而非函数名来调用函数的。
void (*funcp)();
void FileFunc(),EditFunc();
main()
{
funcp=FileFunc;
(*funcp)();
funcp=EditFunc;
(*funcp)();
}
void FileFunc()
{
printf(FileFunc\n);
}
void EditFunc()
{
printf(EditFunc\n);
}
程序输出为:
FileFunc
EditFunc
总结
主要的区别是一个是指针变量,一个是函数。在使用是必要要搞清楚才能正确使用.