精华内容
下载资源
问答
  • Error:指向绑定函数指针只能用于调用函数

    千次阅读 多人点赞 2020-10-08 00:14:03
    Error:指向绑定函数指针只能用于调用函数 调用函数的时候没有加上括号。

    Error:指向绑定函数的指针只能用于调用函数

    调用函数的时候没有加上括号。

    展开全文
  • 指向函数指针 指向函数指针的数组

    1、指向函数的指针


    对于一个函数只能做两件事情:调用它,或是取得它的地址。
    可以取得函数的地址并赋值给指向函数的指针,并在以后使用这个指针调用该函数。

    void fun(int num)
    {
    	cout << num << endl;
    }
    
    void (*pfun)(int num);//pfun此时就是一个函数指针
    
    int main()
    {
    	int value = 100;
    	
    	pfun = &fun;//获得函数fun的地址
    	pfun(value);//等价于调用 fun(value);
    	
    	//取地址运算符&可以不要;
    	pfun = fun;
    	pfun(value);//也是等价于调用 fun(value);
    
    	return 0;
    }

    指向函数的指针的声明中也需要给出参数类型和返回值类型。指向函数的指针只能被参数类型和返回值类型都一样的函数赋值。

    比如:
    void (*pfun)(string);
    void f1(string){}
    int f2(string) {}
    void f3(int){}
    pfun = f1;//正确
    pfun = f2;//不正确,返回值类型不同
    pfun = f3;//不正确,参数类型不同


    2、指向函数的指针的数组

    typedef void (*PF)();
    PF edit_opts[] = {&f1, &f2, &f3};//edit_opts就是指向函数指针的数组,数组里面每个元素的类型都是void (*PF)();
    展开全文
  • 函数指针的初始化 函数如下: int CompareString(const string&amp; str1, const string&amp; str2) { return str1.compare(str2); } 函数的初始化有两种方式: 第一种,也是最普遍的方式: int...

    函数指针的初始化

    函数如下:

    int CompareString(const string& str1, const string& str2)
    {
        return str1.compare(str2);
    }

    函数的初始化有两种方式:

    第一种,也是最普遍的方式:

    int (*CompareFunction)(const string&, const string&) = CompareString;

    第二种,是使用 typedef 定义函数类型,这种写法有助于对代码的理解:

    typedef int (*CompareFunctionType)(const string&, const string&);
    CompareFunctionType CompareFunction = CompareString;

    函数指针赋值

    函数名可以理解为该类型函数的指针。当然,取地址操作符作用于函数名上也能产生指向该类型函数的指针。也就是说下面两种赋值都是可行的:

    CompareFunctionType CompareFunction = CompareString;
    CompareFunctionType CompareFunction = &CompareString;

    函数调用

    无论是用函数名调用,还是用函数指针调用,还是用显式的指针符号调用,其写法是一样的:

    CompareString("abc", "cba");
    CompareFunction("abc", "cba");
    (*CompareFunction)("abc", "cba");

    函数指针的数组

    对于函数指针的数组,强烈建议使用typedef方式定义类型之后再使用,不然影响代码的阅读性,继续以以上例子为例:

    //without typedef
    int (*CompareFunctionArray[3])(const string&, const string&);
    //with typedef
    CompareFunctionType CompareFunctionTypeArray[3];

    函数指针用做函数返回值的类型

    到这一步,会发现 typedef 是多么的好用了。不然我是完全读不懂下面语句的意思的:

    //without typedef
    int (*func(int*, int))(const string&, const string&);

    上面的声明,将func(int*, int)声明为一个函数,返回值为函数指针,函数类型为int (*)(const string&, const string&)。多么的晦涩啊!如果写成 typedef 就不用这么纠结了,足见 typedef 的作用:

    CompareFunctionType func(int*, int);

    上面所有的内容总结了普通函数指针的声明、定义以及调用,还有函数指针数组,函数指针用作返回值等。但是作为C++的研读,我发现我漏掉了一个最重要的内容,就是指向类成员的指针,这里将做相应补充。指向类成员的指针总的来讲可以分为两大类四小类(指向数据成员还是成员函数,指向普通成员还是静态成员),下面一一做介绍:

    指向类的普通成员的指针(非静态)

    指向类成员函数的指针

    简单的讲,指向类成员函数的指针与普通函数指针的区别在于,前者不仅要匹配函数的参数类型和个数以及返回值类型,还要匹配该函数指针所属的类类型。总结一下,比较以下几点:
    1. 参数类型和个数
    2. 返回值类型
    3. 所属的类类型(特别之处)

    究其原因,是因为非静态的成员函数必须被绑定到一个类的对象或者指针上,才能得到被调用对象的this指针,然后才能调用指针所指的成员函数(我们知道,所有类的对象都有自己数据成员的拷贝,但是成员函数都是共用的,为了区分是谁调用了成员函数,就必须有this指针,this指针是隐式的添加到函数参数列表里去的)。明白了这点,接下来就简单了。

    声明:与普通函数作为区分,指向类的成员函数的指针只需要在指针前加上类类型即可,格式为:

    typedef 返回值 (类名::*指针类型名)(参数列表);

    赋值:只需要用类的成员函数地址赋值即可,格式为:

    指针类型名  指针名 = &类名::成员函数名;

    注意:这里的这个&符号是比较重要的:不加&,编译器会认为是在这里调用成员函数,所以需要给出参数列表,否则会报错;加了&,才认为是要获取函数指针。这是C++专门做了区别对待。

    调用:调用方法也很简单,针对调用的对象是对象还是指针,分别用.和->进行调用,格式为:

    (类对象.*指针名)(参数列表);
    (类指针->*指针名)(参数列表);

    注意:这里的前面一对括号是很重要的,因为()的优先级高于成员操作符指针的优先级。

    下面举个简单的例子就一目了然了:

    class A;
    typedef void (A::*NONSTATICFUNCPTR)(int);    //typedef
    
    class A
    {
    public:
        void NonStaticFunc(int arg)
        {
            nonStaticMember = arg;
            cout<<nonStaticMember<<endl;
        }
    private:
        int    nonStaticMember;
    };
    
    int main()
    {
        NONSTATICFUNCPTR funcPtr= &A::NonStaticFunc;
    
        A a;
        (a.*funcPtr)(10);        //通过对象调用
    
        A *aPtr = new A;
        (aPtr->*funcPtr)(10);    //通过指针调用
    
        return 0;
    }

    指向类数据成员的指针

    成员函数搞懂了,数据成员也就easy了,只要判断以下两点是否一致即可:
    1. 数据成员类型
    2. 所属的类类型

    另外,声明、赋值还有调用方法等这些是和前面类似的,再举个例子吧:

    class A;
    typedef int (A::*NONSTATICDATAPTR);        //typedef
    
    class A
    {
    public:
        A(int arg):nonStaticMember(arg){}
        int    nonStaticMember;
    };
    
    int main()
    {
        NONSTATICDATAPTR dataPtr= &A::nonStaticMember;
    
        A a(10);
        cout<<a.*dataPtr;        //通过对象引用
    
        A *aPtr = new A(100);
        cout<<aPtr->*dataPtr;    //通过指针引用
    
        return 0;
    }

    运行结果,当然是各自输出10100啦。

    指向类的静态成员的指针

    类的静态成员和普通成员的区别在于,他们是不依赖于具体对象的,所有实例化的对象都共享同一个静态成员,所以静态成员也没有this指针的概念。所以,指向类的静态成员的指针就是普通的指针。看下面的例子就明白了:

    typedef const int *STATICDATAPTR;
    typedef int (*STATICFUNCPTR)();        //跟普通函数指针是一样的
    
    class A
    {
    public:
        static int StaticFunc() { return staticMember; };
        static const int staticMember = 10;
    };
    
    int main()
    {
        STATICDATAPTR dataPtr = &A::staticMember;
        STATICFUNCPTR funcPtr = &A::StaticFunc;
    
        cout<<*dataPtr;            //直接解引用
        cout<<(*funcPtr)();
    
        return 0;
    }

    最后注明一下,显然的,要使用(&类名::成员名)获取指向成员的指针,首先这个成员必须是对外可见的哦,即public的,不然是没有权限获取的。

    总结

    写到此,简单总结一下就是:
    1. 静态的和普通的函数指针没啥区别;
    2. 非静态的加一个类局限一下即可。

    不知道以后还会不会有函数指针相关的内容,先到此完结吧。有错误欢迎指正,我会及时修改。

    相关文档

    C++成员函数指针的应用

    展开全文
  • 类成员函数指针和普通函数指针

    千次阅读 2019-04-19 22:07:57
    所以在绑定函数的时候也会发生很多的不同的情况,本文就函数指针可能出现的各种情况一一进行分析。 测试目录: 1.普通函数指针指向普通函数 2.普通函数指向非静态成员函数 3. 类外部的 类函数指针 指向普通函数 4. ...

    前言:

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

    测试目录:

    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

    展开全文
  • 指向函数指针(一)

    万次阅读 多人点赞 2012-04-16 00:08:03
    之所以想写一篇函数指针的文章,源于函数指针在C/C++编程中使用的广泛性,而对于一些初级编程者来说对函数指针的使用或许有些迷惑,而一旦在适当的时候使用了函数指针,会使代码简洁有力。本篇介绍的是函数指针的...
  • 指向成员函数指针

    2011-03-18 17:10:00
    指向成员函数指针 取一个非静态成员函数的地址,如果该函数是nonvirtual,则得到的结果是它在内存中真正的地址。然而这个值也不是完全的,它也需要被绑定于某个class object的地址上,才能够通过它调用...
  • 指向成员函数指针

    2011-09-19 18:35:36
    指向成员函数指针 取一个非静态成员函数的地址,如果该函数是nonvirtual,则得到的结果是它在内存中真正的地址。然而这个值也不是完全的,它也需要被绑定于某个class object的地址上,才能够通过它调用该函数。...
  • 详解函数指针和类成员函数指针

    千次阅读 多人点赞 2017-11-12 21:35:56
    函数指针,顾名思义即指向函数的指针。 如果要问,为什么能用一个指针指向一个函数呢?我觉得要理解这个问题,以及要理解后面的函数指针和类成员函数指针,没有什么比从计算机原理的角度来理解更容易了。这里就简要...
  • 与普通的指针一样,函数指针也是指针,但是不同的是函数指针指向的不是类型,而是函数地址。函数指针是通过指向函数的指针间接调用函数。相信很多人对指向一般函数的函数指针使用的比较多,而对指向类成员函数的函数...
  • Q1:非静态成员函数的地址•... ○ 非静态数据成员的地址是其在类的布局中的位置(加1),是一个不完整的值,需要将其绑定在一个类对象上,才能进行存取○ 非静态函数成员(非虚)的地址是其在内存中的真正地址,但仍是
  • 一、函数指针(不是类的成员函数): 1、指针变量也可以指向一个函数。C在编译时,每一个函数都有一个入口地址,该入口地址就是函数指针指向的地址,这个函数入口地址就称为函数的指针。 2、函数指针的作用: (1)...
  • 先来分析一下int * (*ptr)() 1.由于小括号的运算级比较高,结合方法又是自左向右,所以...4.那么int * (*ptr)()表明定义了一个指针变量ptr,它指向一个没有参数,并且返回值是一个整型指针函数。这就叫做指向函数
  • 普通函数指针、成员变量指针与成员函数指针(一)普通函数指针首先先说普通函数指针,对于函数指针总是与指针函数混淆,那么他们的区别在哪呢?1、指针函数 int* f(int a;int b) //函数名为f,返回值为int类型的...
  • 前面曾写过一篇恼人的函数指针(一),总结了普通函数指针的声明、定义以及调用,还有函数指针数组,函数指针用作返回值等。但是作为C++的研读,我发现我漏掉了一个最重要的内容,就是指向类成员的指针,这里将做...
  • //cmpFcn是一个指向函数的指针类型,所以pf1是一个函数指针,但是还没有绑定到一个函数 cmpFcn pf2 = lengthCompare;//函数指针pf2指向函数lengthCompare,他们的类型完全匹配 pf1=lengthCompare; pf2=pf1;//可以...
  • C++中 指向成员函数指针

    千次阅读 2014-05-04 16:46:03
    当我第一次遇见他们的时候,有关如何定义、使用指向类成员函数的函数指针的资料十分难寻找。(ps:这是几年前的事儿,也许现在C++的入门指南包括了这些),所以在此记录如何使用他们。 首先我们先看最简单的情况...
  • 指向模板类成员函数的函数指针

    千次阅读 2012-10-08 10:20:54
    c++标准不支持模板函数指针,比如: template typedef int (* Func) (constType& type);//提示编译错误 不过我们可以这样写: template class CAggCalculator { private: typedef bool (CAggCalculator::*...
  • C++ Primer 指向成员函数指针

    千次阅读 2006-12-21 18:36:00
    下面的pfi 是一个函数指针该函数没有参数返回类型为intint (*pfi) ();给出两个全局函数HeightIs()和WidthIs()int HeightIs();int WidthIs();把HeightIs()和WidthIs()中的任何一个或两个赋值给指针pfi 都是合法且正确...
  • 函数指针及其应用 ◆ 1、函数名与函数指针 函数名对应于该函数执行代码的入口地址。通过取地址运算符“&”也可以取得函数的入口地址。指向函数的指针可以作为函数的参数传递。定义方式如下:  返回类型 (*指针...
  • C++类成员函数指针使用介绍

    万次阅读 多人点赞 2019-09-21 16:07:49
    在之前写过的博客中有介绍过函数指针和指针函数的区别和简单用法(文章在这里),当时的Demo非常简单,都是C语言的写法,但是当在C++中直接像C那样使用类成员函数指针时就会报错:reference to non-static member ...
  • 我们首先复习一下”指向函数指针”如何使用? void print()  {  }  void (*pfun)(); //声明一个指向函数指针,函数的参数是 void,函数的返回值是 void  pfun = print; //赋值一个指向函数指针  (*pfun)();...
  •  顾名思义,函数指针指向函数之指针,它与其他普通类型指针一样,所占内存为4个字节(32位系统)。所不同的是其内部存储了函数的地址而非数据地址,函数指针可以实现对参数类型、参数顺序、返回值都相同的函数进行...
  • 函数指针指向的函数为空参数,返回整型; 2. 回调函数是一个程序员不能显式调用的函数;通过将回调函数的地址传给被调用者从而实现调用。 回调函数是一个通过函数指针调用的函数。如果你把函数的指针...
  • 函数指针

    2011-09-07 15:31:36
    这篇文章把函数指针的各种常用情况做了一个详解的总结。   1. 指向普通函数的指针   很简单,如下的例子可以说明基本格式和用法:   int int_add(int a, int b) { return (a+b); } int
  • C/C++ 函数指针 总结

    千次阅读 2013-08-06 10:34:29
    什么是函数指针 就像某一变量的地址可以存储在相应的指针变量中一样,指向函数的指针中保存着函数代码起始处的地址 ... //pf是一个函数指针,它指向的函数类型为:返回值为void,参数列表为(int, int)
  • GetRef 函数 返回一个指向一过程的引用,此过程可绑定某事件。 Set object.eventname = GetRef(procname) 参数 object 必选项。事件所关联的对象的名称。 eventname 必选项。要与函数绑定的事件的名称。 procname 必...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 97,055
精华内容 38,822
关键字:

指向绑定函数的指针