指向方法的麻烦

时间:2012-01-24 17:46:18

标签: c++ pointers methods

我只是在学习C ++,而且我在指向方法方面遇到了困难。让我们说:

class One {
public:
int Add (int a, int b) {return a+b;}
};

typedef int (One::*pAdd) (int, int);

class Other {
public:
int Next (pAdd funct, int c){ return funct (c, 1);}

};

int main (){

One one;
Other other;

other.Next(one.Add, 2);

return 0;
}

我有很多问题,正如我的MinGW报道的那样。首先,我没有正确调用函数,因为编译器坚持使用。*或 - > *。不知道如何纳入此请求,欢迎任何帮助。现在,我可以通过使方法静态使用c样式指针或传递对象并从Next中调用方法来解决我的问题,但我想理解指向方法的指针。基本上,我很困惑为什么一个。添加不是一个可接受的输入。调用方法是明确定义的(.Add)并符合我的typedef。另外,我从typedef提供了类(一)的实例,从而提供了执行方法的上下文。但编译器输出看起来像我不仅错过了语法,但我错过了这个概念。那么,如何将指向对象的方法作为上下文作为单个参数传递?

4 个答案:

答案 0 :(得分:6)

这里的主要问题是成员函数与对象实例没有关联,它们只是具有略微不同签名的函数指针。

因此,当你想调用一个成员函数时,你需要做两件事:一个指向成员函数的指针对象实例来调用它。

我稍微更改了您的代码示例:

#include <iostream>

class One {
public:
    int Add (int a, int b) {return a+b;}
};

typedef int (One::*pAdd) (int, int);

class Other {
public:
    int Next (One one, pAdd funct, int c){
        return (one.*funct)(c, 1);
    }
};

int main (){
    One one;
    Other other;

    std::cout << other.Next(one, &One::Add, 2) << std::endl;

    return 0;
}

现在it works。它可能会有所改进,但我认为你可以从这里开始。

我建议您阅读Pointers to member functionsc++ faq lite部分,这很好地解释了这一点。

答案 1 :(得分:1)

  

那么,如何将指向对象的方法作为上下文作为单个参数传递?

只使用成员函数指针,你不能。虽然你的语法看起来应该这样做,但是不允许这样做。您需要一个对象将该函数应用于:

class Other {
public:
    int Next (pAdd funct, One & o, int c){ return (o.*funct) (c, 1);}
}

int main (){
    One one;
    Other other;
    other.Next(&One::Add, one, 2);
}

如果要创建一个调用特定对象的特定成员函数的函数对象,那么一种可能性是使用std::bind(或boost::bind如果你不能使用C ++ 11还):

#include <functional>

class Other {
public:
    int Next (std::function<int(int,int)> funct, int c){ return funct (c, 1);}
};

int main (){
    One one;
    Other other;

    using namespace std::placeholders;
    other.Next(std::bind(&One::Add, &one, _1, _2), 2);
}

或lambda:

other.Next([&](int a, int b){return one.Add(a,b);}, 2);

答案 2 :(得分:0)

指向成员的指针需要一个实例来操作。本质上,它们是带有一个加法参数的函数,该参数成为隐式this指针。要通过指向当前对象的成员的指针来调用函数,可以使用如下代码:

(this->*funct)(c, 1);

(您可以类似地访问成员变量但没有函数调用)。

您调用该成员的对象不是指向成员的指针的一部分。因此,你需要得到这样的东西:

&One::Add

如果成员函数过载,这会变得更有趣:在这种情况下,您需要提供一个上下文,从中可以在获取地址时确定重载。我为此愚蠢地使用static_cast<>()

static_cast<int (One::*)(int,int)>(&One::Add)

答案 3 :(得分:0)

这里有一堆问题:one.Add是一个成员函数 你不能只是调用它。你需要有一个指向类的指针 也可以调用它。此外,您需要使用特殊operator.*operator->*。您也不能获取绑定成员的地址 功能

总而言之,您应该使用模板和boost/std::bind来制作 这一切都可以忍受或远离它。

这是修改后的工作代码:

class One {
public:
  int Add (int a, int b) {return a+b;}
};

typedef int (One::*pAdd) (int, int);

class Other {
public:
  int Next (One* one, pAdd funct, int c){ return (one->*funct)(c, 1);}
};

int main (){

  One one;
  Other other;

  other.Next(&one, &One::Add, 2);

  return 0;
}