您的位置:首页 > 其它

int * (*ptr)()怎么理解(指向函数的指针)

2017-09-17 15:41 288 查看
先来分析一下int * (*ptr)()

1.由于小括号的运算级比较高,结合方法又是自左向右,所以先运算(*ptr),表明定义了一个指针ptr
2.接下来再运算最右边的小括号(),表明是一个函数
3.接下平再运算* (*ptr)(),表明函数的返回值是一个指针
4.那么int * (*ptr)()表明定义了一个指针变量ptr,它指向一个没有参数,并且返回值是一个整型指针的函数。
这就叫做指向函数的指针,虽然以前听人说大多都是在回调函数中用,但是一直感觉和普通函数每什么区别,今天看了一个博客算是多多少收懂了一下,下面的博文有点长,不过如果你看懂了相信收货一定会不小的(起码我懂了回调函数到底是怎么一回事~~)。

博文原址http://blog.csdn.net/hzyong_c/article/details/7464202

首先,先介绍一下指向函数的指针

函数指针在C/C++编程中使用的广泛性,而对于一些初级编程者来说对函数指针的使用或许有些迷惑,而一旦在适当的时候使用了函数指针,会使代码简洁有力。本篇介绍的是函数指针的基础部分,函数指针复杂的应用将在下一篇介绍。


一 指向普通函数的指针

先来看一个函数:

[cpp] view
plain copy

int Sum(int a, int b)

{

return a + b;

}

这个函数,调用方式可以如

Sum(1, 2);

若要表示函数的指针,可以用&Sum,也可以将Sum前边的地址操作符&去掉,对于普通函数,地址操作符&是可选的

下面介绍函数指针变量和函数指针类型:

1. 函数指针变量

[cpp] view
plain copy

int (*FnName)(int, int); // 声明一个函数指针,可以将FnName理解为新定义的变量

FnName = ∑ // 将Sum函数的地址赋给它

(*FnName)(3, 5); // 和调用Sum(3, 5)的效果是一样的

第1行声明了一个函数指针变量,如果有疑问,可以将FnName理解为一个新定义的变量。函数指针变量的声明格式:

返回类型(*函数指针变量)(参数列表);

第2行将Sum函数指针赋给它,注意,只有两个函数指针参数类型,返回值类型完全相同才可以赋值,注意修饰符const,&等不同也会导致赋值失败。

第3行是调用,调用格式:

(*函数指针变量)(实参列表);

2. 函数指针类型

前面介绍了函数指针变量的声明,那么函数指针类型如何声明呢?
在函数指针声明前面加个typedef就成了函数指针类型定义。

[cpp] view
plain copy

typedef int (*FnType)(int, int); // 声明一个函数指针类型

FnType fb = ∑ // 定义一个FnType类型的变量,并赋值

(*fb)(3, 5); // 函数调用

第1行声明函数指针的类型,FnType便是新声明的类型,它是函数指针的类型。

第2行定义一个FnType类型的变量,并将Sum函数地址赋值给它。

第3行是函数调用。
前面已经了解了函数指针的变量和类型,看下面的代码加深下理解:

[cpp] view
plain copy

int Sum(int a, int b)

{

return a + b;

}

typedef int (*FnType)(int, int);

int Fun1(FnType ft, int x, int y)

{

return (*ft)(x, y);

}

// 函数指针可以定义在参数列表中,在函数体内使用

int Fun2(int (*fn)(int, int), int x, int y)

{

return (*fn)(x, y);

}

int main()

{

cout << Fun1(&Sum, 2, 3) << " "; // 输出 5

cout << Fun2(&Sum, 3, 4) << "\n"; // 输出 7

return 0;

}

关于普通函数指针的学习就到这里吧,简单吧:),下面就来学习类的成员函数的指针。


二 指向类成员函数的指针

先看下面这个类:

[cpp] view
plain copy

class Num

{

public:

Num(){n_ = 0;}

void Inc(int n);

void Dec(int n);

static int Sub(int a, int b);

private:

long n_;

};

这个类中有普通成员函数,也有静态成员函数,无论哪种函数,函数指针表示方式都是:

&类名::函数名

如Num类三个成员函数的指针分别是:

&Num::Inc;

&Num::Dec;
&Num::Sub;

1. 指向普通成员函数的指针

声明一个指向类成员函数的指针时需要用到::*符号,左边是类名,右边是成员函数指针名:

返回类型 类名::*成员函数指针(参数列表);

调用的时候要用到.*或->*,左边是类对象的引用或指针,右边是成员函数指针:

(对象名.* 成员函数指针)(实参);



(对象指针->* 成员函数指针)(实参);

代码示例:

[cpp] view
plain copy

int main()

{

Num obj;

void (Num::*mf)(int); // 声明指向成员函数的指针 mf

mf = &Num::Inc; // 赋值

(obj.*mf)(1); // 调用

// 成员函数的指针类型

typedef void (Num::*mt)(int);

mt fn = &Num::Dec;

(obj.*fn)(2);

return 0;

}

注意上面,Sub是静态成员函数,其指针声明跟非静态成员函数不一样,下面来看静态成员函数的指针。
2. 指向静态函数的指针

[cpp] view
plain copy

int (*smf)(int a, int b); // 注意写法

smf = &Num::Sub;

cout << (*smf)(6, 7); // 调用方式跟上一节讲的普通函数调用方式一样

可以看到,静态成员函数指针变量、类型声明与普通函数一致。

3. 指向虚函数的指针

先上代码:

[cpp] view
plain copy

class Base{

public:

virtual void F() const

{

cout << "I am the Base\n";

}

typedef void (Base::*FnPtr)() const;

};

class Derived : public Base{

public:

virtual void F() const

{

cout << "I am the Derived\n";

}

};

int main()

{

Base::FnPtr fp = &Base::F;

Base base;

(base.*fp)();

Derived derived;

(derived.*fp)();

return 0;

}

输出结果:

I am theBase

I am theDerived
可见,虚函数的指针调用结果跟直接调用虚函数效果一样,虚函数的指针指向的函数地址是对象动态绑定的函数地址。

接下来,介绍一下函数指针在回调函数的应用

模板类,该类拥有2个成员,一个是对象指针,一个是成员函数,成员函数必须无参,无返回值。

[cpp] view
plain copy

struct CallbackAction {

virtual void Execute() = 0;

virtual ~CallbackAction() {}

};

template <class OBJECT, class METHOD>

struct CallbackMethodAction : public CallbackAction {

OBJECT *object;

METHOD method;

void Execute() { (object->*method)(); }

CallbackMethodAction(OBJECT *object, METHOD method) : object(object), method(method) {}

};

为使用起来方便,进一步封装。

[cpp] view
plain copy

class Callback{

public:

explicit Callback(CallbackAction *newaction) { action = newaction; }

Callback() { action = NULL; }

~Callback();

Callback(const Callback& c);

Callback& operator=(const Callback& c);

void Execute() const { if(action) action->Execute(); }

void operator()() const { Execute(); }
//这里重写了()

private:

CallbackAction *action;

};

Callback::Callback(const Callback& c)

{

action = c.action;

}

Callback::~Callback()

{

}

Callback& Callback::operator=(const Callback& c)

{

action = c.action;

return *this;

}

为调用方便,再增加一个接口函数,注意,这里进行了new操作,没有delete,会造成内存泄露,本例没有处理内存问题,解决这个问题,可以再Callback类里添加计数器,管理指针。

[cpp] view
plain copy

template <class OBJECT, class METHOD>

Callback callback(OBJECT *object, void (METHOD::*method)()) {

return Callback(new CallbackMethodAction<OBJECT, void (METHOD::*)()>(object, method));

}

看一下如何应用

[cpp] view
plain copy

class Girl

{

public:

void Shopping()

{

cout << "I want to shopping" << endl;

WhenShopping();

}

Callback WhenShopping;

};

class Boy

{

public:

void Bind(Girl* girl)

{

girl->WhenShopping = callback(this, &Boy::OnShopping);
//这里就是指 //向函数的指针

}

private:

void OnShopping() {cout << "I know she is shopping" << endl;}

};

客户端调用

[cpp] view
plain copy

void main()

{

Girl girl;

Boy boy;

boy.Bind(&girl); //这里可以看出回调的端倪,其实回调是在绑定的时候把要响应的对象值赋给调用的对象,当调用对象遇到重载后的括号()就会执行响应的动作

girl.Shopping();

}

输出结果:

I want to shopping
I know she is shopping

上面的的代码只是个callback使用的雏形,没有处理内存问题和由const修饰的参数问题,直接使用会有内存泄露。另外,如果需要带参数的函数指针类型,需要再扩展。
//下面的我也没看过了。。。。。。。。。。。。

下面是带1个参数和带2个参数的函数指针类型的应用,更多参数的函数指针这里就不再展示了。

[cpp] view
plain copy

template <class P1>

struct Callback1Action {

virtual void Execute(P1 p1) = 0;

virtual ~Callback1Action() {}

};

template <class OBJECT, class METHOD, class P1>

struct Callback1MethodAction : public Callback1Action<P1> {

OBJECT *object;

METHOD method;

void Execute(P1 p1) { (object->*method)(p1); }

Callback1MethodAction(OBJECT *object, METHOD method) : object(object), method(method) {}

};

template <class P1>

class Callback1{

public:

explicit Callback1(Callback1Action <P1> *newaction) { action = newaction; }

Callback1() { action = NULL; }

~Callback1();

Callback1& operator=(const Callback1& c);

Callback1(const Callback1& c);

void Execute(P1 p1) const { if(action) action->Execute(p1); }

void operator()(P1 p1) const { Execute(p1); }

private:

Callback1Action<P1> *action;

};

template <class P1>

Callback1<P1>& Callback1<P1>::operator=(const Callback1& c)

{

action = c.action;

return *this;

}

template <class P1>

Callback1<P1>::Callback1(const Callback1& c)

{

action = c.action;

}

template <class P1>

Callback1<P1>::~Callback1()

{

}

// 接口函数

template <class OBJECT, class METHOD, class P1>

Callback1<P1> callback(OBJECT *object, void (METHOD::*method)(P1 p1)) {

return Callback1<P1>(new Callback1MethodAction<OBJECT, void (METHOD::*)(P1 p1), P1>(object, method));

}

[cpp] view
plain copy

template <class P1, class P2>

struct Callback2Action {

virtual void Execute(P1 p1, P2 p2) = 0;

virtual ~Callback2Action() {}

};

template <class OBJECT, class METHOD, class P1, class P2>

struct Callback2MethodAction : public Callback2Action<P1, P2> {

OBJECT *object;

METHOD method;

void Execute(P1 p1, P2 p2) { (object->*method)(p1, p2); }

Callback2MethodAction(OBJECT *object, METHOD method) : object(object), method(method) {}

};

template <class P1, class P2>

class Callback2{

public:

explicit Callback2(Callback2Action <P1, P2> *newaction) { action = newaction; }

Callback2() { action = NULL; }

~Callback2();

Callback2& operator=(const Callback2& c);

Callback2(const Callback2& c);

void Execute(P1 p1, P2 p2) const { if(action) action->Execute(p1, p2); }

void operator()(P1 p1, P2 p2) const { Execute(p1, p2); }

private:

Callback2Action<P1, P2> *action;

};

template <class P1, class P2>

Callback2<P1, P2>& Callback2<P1, P2>::operator=(const Callback2& c)

{

action = c.action;

return *this;

}

template <class P1, class P2>

Callback2<P1, P2>::Callback2(const Callback2& c)

{

action = c.action;

}

template <class P1, class P2>

Callback2<P1, P2>::~Callback2()

{

}

template <class OBJECT, class METHOD, class P1, class P2>

Callback2<P1, P2> callback(OBJECT *object, void (METHOD::*method)(P1 p1, P2 p2)) {

return Callback2<P1, P2>(new Callback2MethodAction<OBJECT, void (METHOD::*)(P1 p1, P2 p2), P1, P2>(object, method));

}

应用代码

[cpp] view
plain copy

class Girl

{

public:

void Shopping()

{

cout << "I want to shopping" << endl;

WhenShopping();

WhenBuy("fruits");

WhenBuy("chocolate");

WhenPay(20, 16);

}

void Swimming()

{

cout << "I want to swimming" << endl;

WhenSwimming();

}

Callback WhenShopping;

Callback WhenSwimming;

Callback1<string> WhenBuy;

Callback2<int, int> WhenPay;

};

class Boy

{

public:

void Bind(Girl* girl)

{

girl->WhenShopping = callback(this, &Boy::OnShopping);

girl->WhenSwimming = callback(this, &Boy::OnSwimming);

girl->WhenBuy = callback(this, &Boy::OnBuy);

girl->WhenPay = callback(this, &Boy::OnPay);

}

private:

void OnShopping() {cout << "I know she is shopping" << endl;}

void OnSwimming() {cout << "I know she is swimming" << endl;}

void OnBuy(string thing) {cout << "She buy " << thing << endl;}

void OnPay(int a, int b) {cout << "She pay " << a << " " << b << endl;}

};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐