类成员函数指针区别于用法

简介: 通常的函数指针大家已经非常熟悉了。但我们今天讨论一下类成员函数指针的用法。 今天我们来看一下成员函数指针,加入我们想要声明一个 void CTest::Show()成员函数指针类型,那么我们一般的做法是: typedef void(CTest::*pShow)(); 从上面可以看出一些和一般函数指针类型不同的地方。

通常的函数指针大家已经非常熟悉了。但我们今天讨论一下类成员函数指针的用法。

今天我们来看一下成员函数指针,加入我们想要声明一个 void CTest::Show()成员函数指针类型,那么我们一般的做法是:

typedef void(CTest::*pShow)();

从上面可以看出一些和一般函数指针类型不同的地方。让我们把他和一般的函数声明比较一下。下面是一般的函数声明:

typedef void(*pShow)();

我们可以看出成员函数指针和一般函数指针的不同,那就是成员函数指针声明时加上类限制。这会起到什么作用呢?和类成员函数一样,那就是编译器会在编译的时候在函数指针对应的函数调用中加上this指针。所以类成员函数不能单独调用,一定要注意。必须与类对象配合调用。

 

下面是一个简单的成员函数指针类型的使用例子:

#include "stdafx.h"
#include <iostream>

using namespace std;
class Test

{

 int sum;

public:

 Test():sum(0){}

 int Add(int a,int b) {return (sum = a + b);}

 void Show() {cout<<"Show()";}

};

 

 

//////////////////////////////////////////////////////////cpp//////////////////////////////////////////////////////////////////////////

 

 

typedef void(Test::*pShow)();
typedef int(Test::*pAdd)(int,int);


int _tmain(int argc, _TCHAR* argv[])

{

 Test t;

 pShow Show=&Test::Show;
 pAdd  Add=&Test::Add;


 (t.*Show)();
 cout<<(t.*Add)(2,5);

}

结果:Show()7

注意其中特别的语法:

1:给指针变量赋值时,要在用来赋值的成员函数名前面加'&'符号。

2:注意(t.*Add)(2,5)可不能能写成t.*Add(2,5);因为括号的优先级比*高。所以要写成(t.*Add)(2,5)或者(t.Add)(2,5)。后者之所以可以,因为函数名本身可以当地址,但C++同时也支持&函数名为取函数地址。这关系到如果看待函数名以处理函数指针的重要问题。

 

既然说到成员函数指针的那么,我们很可能会想到它是否具有向类的函数一样的特殊性质,特别是虚函数?是的,成员函数指针就有虚函数的特性。看下例:

#include "stdafx.h"
#include <iostream>

using namespace std;
class A
{
public:
 virtual void Show() {cout<<"A";}
};

class B:public A
{
public :
 void Show() {cout<<"B";}
};

 

//////////////////////////////////////////////////////////cpp//////////////////////////////////////////////////////////////////////////

 

 

typedef void(A::*pShow)();


int _tmain(int argc, _TCHAR* argv[])

{

 B t;

 pShow Show=(pShow)&A::Show;
 pShow Show=(pShow)&B::Show;

 (t.Show)();
 cin.get();

}

结果:BB

 

通过结果可以看出,虽然声明的基类的虚函数指针,但是函数指针调用时还是根据调用对象来相应的函数,颇像虚函数。所以基类成员函数指针可以根据运行时对象的类型来确定的对应的函数调用。

 

但其中有一个容易忽略的语法:

基类指针=派生类函数地址,这种隐式赋值是不行。也就是说

pShow Show=&B::Show;

编译时不通过的,也就是说C++认为将派生类成员函数名赋给基类成员函数指针是可能存在问题的。可能你会想,我们经常将派生类对象给基类指针啊,

是啊,不过两者不是一回事,考虑的角度不同。

 

前者的解释:基类的函数布局(个数)是派生类的函数布局的子集。所以基类的函数赋给派生类的函数指针时,因为派生类肯定有(public的基类函数)此函数,所以赋值很安全。反过来,你想有可能会出现问题。

后者的解释:基类所做的操作涉及的数据成员不会超出派生类的范围。所以把派生类对象给基类指针,基类来处理没问题。也很安全。反过来呢,你也知道,很危险滴!

 

所以在使用成员函数指针时大家还需多多注意。

相关文章
|
2月前
|
C++
【编码狂想】指针航行,链表魔法,解锁结构体和类的编程幻境
【编码狂想】指针航行,链表魔法,解锁结构体和类的编程幻境
58 1
|
29天前
|
存储 编译器 C语言
【c++】类和对象(二)this指针
朋友们大家好,本节内容来到类和对象第二篇,本篇文章会带领大家了解this指针
【c++】类和对象(二)this指针
|
29天前
|
存储 编译器 C语言
【C++练级之路】【Lv.2】类和对象(上)(类的定义,访问限定符,类的作用域,类的实例化,类的对象大小,this指针)
【C++练级之路】【Lv.2】类和对象(上)(类的定义,访问限定符,类的作用域,类的实例化,类的对象大小,this指针)
|
1月前
|
存储 安全 程序员
【C++ 包装器类 智能指针】完全教程:std::unique_ptr、std::shared_ptr、std::weak_ptr的用法解析与优化 — 初学者至进阶指南
【C++ 包装器类 智能指针】完全教程:std::unique_ptr、std::shared_ptr、std::weak_ptr的用法解析与优化 — 初学者至进阶指南
71 0
|
1月前
|
算法 Java
快慢指针该如何操作?本文带你认识快慢指针常见的三种用法及在链表中的实战
快慢指针该如何操作?本文带你认识快慢指针常见的三种用法及在链表中的实战
21 0
|
1月前
|
存储 C语言
c语言函数指针和指针函数的区别,以及回调函数的使用。
c语言函数指针和指针函数的区别,以及回调函数的使用。
9 0
|
1月前
|
存储 C语言
c语言中strlen与sizeof的区别(指针面试题详解帮你深度区分!)
c语言中strlen与sizeof的区别(指针面试题详解帮你深度区分!)
|
2月前
|
存储 C++
C++类与对象【对象模型和this指针】
C++类与对象【对象模型和this指针】
|
2月前
|
编译器 C语言 C++
C++类和对象的细节原理:this指针、构造函数和析构函数、深浅拷贝、运算符重载、初始化列表、类的各种成员和方法
C++类和对象的细节原理:this指针、构造函数和析构函数、深浅拷贝、运算符重载、初始化列表、类的各种成员和方法
36 0
|
2月前
|
安全 C++
C++智能指针的用法
C++智能指针的用法
32 0