前言:

先声明一下,普通函数指针和类成员函数指针有很大的区别!所以在绑定函数的时候也会发生很多的不同的情况,本文就函数指针可能出现的各种情况一一进行分析。

测试目录:

1.普通函数指针指向普通函数
2.普通函数指向非静态成员函数
3. 类外部的 类函数指针 指向普通函数
4. 类外部的 类函数指针 指向成员函数
5. 类内部的 函数指针 指向成员函数 (类似于第2条)
6. 类内部的 函数指针 指向普通函数

#include <iostream>
#include <string>
#include <vector>
#include <map>
using namespace std;class Foo
{
public:string m_str;Foo(){m_str = "";}static void testFunc2(int a){cout<<"Foo:void testFunc2(int a)"<<endl;cout<<a<<endl;}void testFunc4(int a){cout<<"Foo:void testFunc4(int a)"<<endl;cout<<a<<endl;}static void testFunc5(int a){cout<<"Foo:void testFunc5(int a)"<<endl;cout<<a<<endl;}void (*pTestFunc5)(int a);void (*pTestFunc6)(int a);
};void (*pTestFunc1)(int a);
void (*pTestFunc2)(int a);
void (Foo::*pTestFunc3)(int a);
void (Foo::*pTestFunc4)(int a);void testFunc1(int a)
{cout<<"func1 pointer test"<<endl;cout<<a<<endl;
}void testFunc3(int a)
{cout<<"func3 pointer test"<<endl;cout<<a<<endl;
}void testFunc6(int a)
{cout<<"func6 pointer test"<<endl;cout<<a<<endl;
}int main(int argc, const char *argv[])
{Foo foo;//foo.test("woo",100);pTestFunc1 = testFunc1;       //经常用这个方法(*pTestFunc1)(1);pTestFunc2=&foo.testFunc2;(*pTestFunc2)(2);//pTestFunc3 = &testFunc3;  //编译器报错,不可以这么使用pTestFunc4 = &Foo::testFunc4; //初始化的时候必须带有&Foo:://pTestFunc4(4);//编译器报错,不可以这么使用//foo.pTestFunc4(4);//编译器报错,不可以这么使用//foo.*pTestFunc4(4);//编译器报错,不可以这么使用//foo.(*pTestFunc4)(4);//编译器报错,不可以这么使用(foo.*pTestFunc4)(4);    //正常运行foo.pTestFunc5=&Foo::testFunc5;foo.pTestFunc5(5);foo.pTestFunc6 = &testFunc6;foo.pTestFunc6(6);return 0;
}

程序分析:

1.普通函数指针指向普通函数
pTestFunc = &testFunc;
或者
pTestFunc = testFunc;
调用方式
pTestFunc(1)
(pTestFunc)(1)
(*pTestFunc)(1)

2.普通函数指向非静态成员函数
pTestFunc=foo.testFunc2;  编译器报错,提示不匹配
error: argument of type ‘void (Foo::)(int)’ does not match ‘void (*)(int)’

pTestFunc=&foo.testFunc2;  编译器报错,提示不匹配
error: ISO C++ forbids taking the address of a bound member function to form a pointer to member function.  Say ‘&Foo::testFunc’
error: cannot convert ‘void (Foo::*)(int)’ to ‘void (*)(int)’ in assignment

pTestFunc=Foo::testFunc2;  编译器报错
error: invalid use of non-static member function ‘void Foo::testFunc(int)’

pTestFunc=&Foo::testFunc2; 编译器报错
error: cannot convert ‘void (Foo::*)(int)’ to ‘void (*)(int)’ in assignment

普通函数指向静态成员函数
将代码更改一下后,将成员函数前加入一个static关键字
则下面的初始化方式编译和运行正常
pTestFunc2=Foo::testFunc2;
pTestFunc2=&Foo::testFunc2;
pTestFunc2=foo.testFunc2;
pTestFunc2=&foo.testFunc2;
调用方式和普通函数指向普通函数一致
pTestFunc2(2)
(pTestFunc)2(2)
(*pTestFunc)2(2)

3. 类外部的 类函数指针 指向普通函数
这种用法就是错误的,所以编译器不通过
pTestFunc3 = testFunc3;  编译器报错,
test5.cpp:83: error: cannot convert ‘void(int)’ to ‘void (Foo::*)(int)’ in assignmen
pTestFunc3 = &testFunc3;
test5.cpp:83: error: cannot convert ‘void (*)(int)’ to ‘void (Foo::*)(int)’ in assignmen

4. 类外部的 类函数指针 指向成员函数
初始化指针的方式
pTestFunc4 = &Foo::testFunc4; //初始化的时候必须带有&Foo::
pTestFunc4 = Foo::testFunc4; //编译器报错
pTestFunc4 = foo.testFunc4; //编译器报错
pTestFunc4 = &foo.testFunc4; //编译器报错

调用方式:
pTestFunc4(4);//编译器报错,不可以这么使用
foo.pTestFunc4(4);//编译器报错,不可以这么使用
foo.*pTestFunc4(4);//编译器报错,不可以这么使用
foo.(*pTestFunc4)(4);//编译器报错,不可以这么使用
(foo.*pTestFunc4)(4)//正常运行,所以必须要带有括号
如果foo为指针
Foo *foo=new Foo();
(foo->*pTestFunc4)(4)

5. 类内部的 函数指针 指向成员函数 (类似于第2条)
foo.pTestFunc5=foo.testFunc5;  编译器报错
test5.cpp:125: error: argument of type ‘void (Foo::)(int)’ does not match ‘void (*)(int)’

foo.pTestFunc5=&foo.testFunc5; 编译器报错
test5.cpp:123: error: ISO C++ forbids taking the address of a bound member function to form a pointer to member function.  Say ‘&Foo::testFunc’
test5.cpp:123: error: cannot convert ‘void (Foo::*)(int)’ to ‘void (*)(int)’ in assignment

foo.pTestFunc5=Foo::testFunc5;编译器报错
foo.pTestFunc5=&Foo::testFunc5;  编译器报错

声明为静态函数后(与第2条相似),编译和运行都OK
foo.pTestFunc5=foo.testFunc5;
foo.pTestFunc5=&foo.testFunc5;
foo.pTestFunc5=Foo::testFunc5;
foo.pTestFunc6=&Foo::testFunc5;

6. 类内部的 函数指针 指向普通函数
编译和运行都OK
foo.pTestFunc2=testFunc6;
foo.pTestFunc2=&testFunc6;

转自:https://blog.csdn.net/maojudong/article/details/8194143

类成员函数指针和普通函数指针相关推荐

  1. 【C++】38.类成员变量声明为 对象与指针的区别

    在我们平时写代码或阅读代码时,经常会看到,某个类A中需要使用另一个类B的方法.那么下面会看到两种用法: 一种是直接定义一个B类对象. 一种是在类A中定义一个B类指针: 如: // 头文件 std::s ...

  2. c/c++教程 - 2.4.2.7~8 类对象作为类成员,static静态成员变量函数

    目录 4.2.7 类对象作为类成员 4.2.8 静态成员 相关教程 4.2.7 类对象作为类成员 C++类中的成员可以是另一个类的对象,我们称该成员为 对象成员. 例如: class A {} cla ...

  3. 指向 类成员函数 指针的用法

    C++在使用函数指针调用类成员函数的时候会遇到很多问题,以下是解决办法: 代码 //test.h class CMyc{ public:int fun(int);typedef int (CMyc:: ...

  4. C++ 笔记(16)— 类和对象(类定义、类实例对象定义、访问类成员、类成员函数、类 public/private/protected 成员、类对象引用和指针)

    1. 类的定义 类定义是以关键字 class 开头,后跟类的名称.并在它后面依次包含类名,一组放在 {} 内的成员属性和成员函数,以及结尾的分号. 类声明将类本身及其属性告诉编译器.类声明本身并不能改 ...

  5. 类成员函数指针的语法

    /*类成员函数指针的语法*/ /*****************************类.h文件************************************/ #if !defined ...

  6. C++中空指针调用类成员函数的原理

    有下面的一个简单的类: class CNullPointCall { public:     static void Test1();     void Test2();     void Test3 ...

  7. C++函数指针和类成员函数指针

    一.函数指针--基本形式 char Fun(int n) { return char(n); } //char(*pFun)(int);void main() {char(*pFun)(int);pF ...

  8. 使用std::function 把类成员函数指针转换为普通函数指针

    前言 这是改造前一篇 设计模式  的基础,使通知者不必知道观察者的类名和函数名,只需要知道更新函数的原型即可. 开发环境:WIN7 32位 + VS2010 发现在VS2005中使用std::funt ...

  9. 函数指针以及在类成员函数中应用函数指针

    什么是函数指针 如果在程序中定义了一个函数,那么在编译时系统就会为这个函数代码分配一段存储空间,这段存储空间的首地址称为这个函数的地址.而且函数名表示的就是这个地址.既然是地址我们就可以定义一个指针变 ...

  10. C++ 函数指针 类成员函数指针

    一.函数指针 函数存放在内存的代码区域内,它们同样有地址.如果我们有一个int test(int a)的函数,那么,它的地址就是函数的名字,这一点如同数组一样,数组的名字就是数组的起始地址. 1.函数 ...

最新文章

  1. java代码如何写出打印_java - 为什么这个代码向后写,打印“Hello World!”
  2. Scala花括号和圆括号的区别
  3. 日本那个大户又要抛了?
  4. VIJOS-P1192
  5. springboot几种注入_Spring Boot中使用JdbcTemplate访问数据库
  6. 5个Python特性 越早知道越好的
  7. 枚举函数enumerate
  8. 千万别让海底捞知道你的生日
  9. .NET中的设计模式——一步步发现装饰模式
  10. SquashFs工具制作
  11. K8s:调用Java接口创建容器
  12. Oracle-Linux安装配置python3.6环境
  13. grads插值_常用grads函数
  14. java面向对象简介
  15. MeasureSpec介绍及使用详解
  16. c语言向量乘法,运用C语言实现向量积
  17. 【360校招笔试】第一题:计算表面积
  18. 项目笔记:Arduino读取SD卡
  19. android实现高德地图集成
  20. java 求最大公因数_三种算法求最大公约数——Java实现 | 学步园

热门文章

  1. Feng Shui POJ - 3384
  2. 凸优化笔记(一):仿射集,凸集与锥
  3. CNN(Convolutional Neural Network)
  4. 车身控制器BCM系统功能规范
  5. nodejs 传递参数
  6. SQLiteOpenHelper 崩溃Couldnt read row 0, col -1 from CursorWindow.
  7. 圣思园将于本周日(10月31日)举行Web Service开发大型免费公开课
  8. 【日志分析】Linux日志分析
  9. OFDMA trigger frame
  10. 数据结构考研:数据、数据元素、数据项、数据对象、数据结构的区别/详细解释(计算机/软件工程/王道论坛)