类成员函数作为函数指针

时间:2014-06-12 23:38:11

标签: c++ class function-pointers member-functions

我有一个类,其中一个成员函数实际上是一个函数指针。这样,用户可以覆盖此功能的功能。遗憾的是,我在运行此功能时遇到了一些困难我用g ++编译。

以下是代码:

    #include <iostream>

    using namespace std;

    double fcn_mod(const double &phit){
        return 1.2+phit;
    }

    class Object{
        public:
            Object() {
                fcn_ptr = (double (*)(const double &)) &Object::fcn_default;
            }
            double (*fcn_ptr)(const double &) = NULL;

        private:
            double fcn_default(const double &phit){
                return 3.2+phit;
            }
    };


    int main(){

        Object test1,test2;

        cout << (test1.*fcn_ptr)(2) << endl; // can not compile here

        test2.fcn_ptr = &fcn_mod;
        cout << (test2.*fcn_ptr)(2) << endl; // and here

        cout << "test" << endl;
    }

错误消息是:

    erreur: ‘fcn_ptr’ was not declared in this scope

+++++更新1 +++++

考虑到评论,这里有一个更清洁的版本:

    #include <iostream>

    using namespace std;

    double fcn_mod(const double &phit){
        return 1.2+phit;
    }

    double fcn_default(const double &phit){
        return 3.2+phit;
    }

    class Object{
        public:
            double (*fcn_ptr)(const double &) = NULL;
            Object() {
                fcn_ptr = &fcn_default;
            }

    };


    int main(){

        Object test1,test2;

        cout << (test1.*fcn_ptr)(2) << endl; // can not compile here

        test2.fcn_ptr = &fcn_mod;
        //cout << (test2.*fcn_ptr)(2) << endl; // and here

        cout << "test" << endl;
    }

这也是一种更好的方法:

    #include <iostream>

    using namespace std;

    double fcn_mod(const double &phit){
        return 1.2+phit;
    }

    class Object{
        public:
            Object() {
                fcn_ptr = &fcn_default;
            }
            double (*fcn_ptr)(const double &) = NULL;
        private :
            static double fcn_default(const double &phit){
                return 3.2+phit;
            }
    };

    int main(){
        Object test1,test2;
        cout << (test1.*fcn_ptr)(2) << endl; // can not compile here
        test2.fcn_ptr = &fcn_mod;
        cout << (test2.*fcn_ptr)(2) << endl; // and here
        cout << "test" << endl;
    }

+++++更新2 +++++

如果我想通过此功能访问班级成员怎么办?

最简单的解决方案将无法从fcn_mod中访问类成员(aa)。

#include <iostream>

using namespace std;

double fcn_mod(const double &phit){
    return 1.2 + phit + aa*0.001; // can not compile here
}

class Object{
    public:
        Object() {
            fcn_ptr = &Object::fcn_default;
            aa = 4;
        }
        double (*fcn_ptr)(const double &) = NULL;
        double aa;

    private:
        static double fcn_default(const double &phit){
            return 3.2 + phit + aa*0.001; // and here
        }
};

int main(){
    Object test1,test2;
    cout << (test1.fcn_ptr)(2) << endl;
    test2.fcn_ptr = &fcn_mod;
    cout << (test2.fcn_ptr)(2) << endl;
    cout << "test" << endl;
}

但是使用std :: bind和std :: function的解决方案也没有。我可以将一种“静态”参数传递给函数指针吗?

我添加了网关功能。

#include <iostream>

using namespace std;

double fcn_mod(const double &phit){
    return 1.2 + phit;
}

class Object{
    public:
        Object() {
            fcn_ptr = &Object::fcn_default;
            aa = 4;
        }
        double do_something(const double &phit){
            return this->fcn_ptr(phit+aa*0.001);
        }
        double (*fcn_ptr)(const double &);
        double aa;

    private:
        static double fcn_default(const double &phit){
            return 3.2 + phit;
        }
};

int main(){
    Object test1,test2;
    cout << test1.do_something(2) << endl; // can not compile here
    test2.fcn_ptr = &fcn_mod;
    cout << test2.do_something(2) << endl; // and here
    cout << "test" << endl;
}

2 个答案:

答案 0 :(得分:5)

你想做的事情是行不通的。指向非静态成员函数的指针与指向自由函数的指针不同,因为与后者不同,前者必须在对象的实例上调用。因此,您无法声明一种类型的变量,并为其指定另一种类型的函数的指针。

首先,让我们修复一半代码:

由于fcn_ptr是指向成员函数的指针,因此它的定义必须是:

double (Object::*fcn_ptr)(const double &) = NULL;

然后,构造函数中的强制转换无效。您正在尝试将指向成员函数的指针强制转换为指向自由函数的指针。摆脱演员。

Object() : fcn_ptr(&Object::fcn_default)
{}

最后,当你调用fcn_ptr时,你不能简单地用空气来召唤它。它是Object的数据成员,因此您需要该类的实例才能访问fcn_ptr。所以称之为:

(test1.*(test1.fcn_ptr))(2)

进行所有这些更改,一半代码将编译并生成正确的结果。 Live demo


另一半,您尝试将指向免费功能的指针分配给fcn_ptr仍然无法正常工作,原因如前所述。解决此问题的方法是使用std::function而不是函数指针。

class Object{
    public:
        Object() : fcn_ptr(std::bind(&Object::fcn_default, this, std::placeholders::_1))
        {}
        std::function<double(double const&)> fcn_ptr;

    private:
        double fcn_default(const double &phit){
            return 3.2+phit;
        }
};

然后将其用作:

cout << (test1.fcn_ptr)(2) << endl;

test2.fcn_ptr = &fcn_mod;
cout << (test2.fcn_ptr)(2) << endl;

Live demo

答案 1 :(得分:0)

你没有一个带有“函数指针”的类,而是一个带有数据成员的类,它是一个函数指针。这是一个重要的区别,因为函数不会收到 this 指针,也无法访问受保护或私有成员。

您已正确声明了您的函数指针,但您需要使用.fcn_ptr而不是.*fcn_ptr。我相信这足以解决您的问题。

请注意您使用的是旧的C风格函数指针语法。您可能想要学习C ++函数指针替代方案,包括std::function