【问题标题】:Troubles with pointer to methods方法指针的问题
【发布时间】:2012-01-24 17:46:18
【问题描述】:

我刚刚学习 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 中调用方法来解决我的问题,但我想了解指向方法的指针。基本上,我很困惑为什么 one.Add 不是可接受的输入。要调用的方法是明确定义的(.Add)并符合我的 typedef。另外,我从 typedef 提供类(一个)的实例,从而提供要在其中执行方法的上下文。但是编译器输出看起来我不仅错过了语法,而且还错过了概念。那么,如何将对象作为上下文作为单个参数传递给方法的指针呢?

【问题讨论】:

  • 我刚刚意识到......打开它们并张贴在错误的标签上。我向社区道歉,我该如何删除问题?
  • @gxs 让它被迁移。
  • 您好 gxs,版主会收到通知,以便您的问题可以自动移至 StackOverflow。这是程序员,是一个关于软件开发的概念性问题的站点。有关详细信息,请参阅FAQ

标签: c++ pointers methods


【解决方案1】:

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

因此,当您要调用成员函数时,您需要两件事:指向成员函数的指针和调用它的对象实例。 p>

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

#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。它可能可以改进一点,但我认为你可以从这里开始。

我建议您阅读c++ faq litePointers to member functions 部分,它很好地解释了这一点。

【讨论】:

    【解决方案2】:

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

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

    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(如果你还不能使用C++11,则使用boost::bind):

    #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);
    

    【讨论】:

      【解决方案3】:

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

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

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

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

      &One::Add
      

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

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

      【讨论】:

        【解决方案4】:

        你有一堆问题:one.Add 是一个成员函数并且 你不能只是调用它。你需要有一个指向类的指针 也调用它。另外,您需要使用特殊的operator.*operator-&gt;*。也不能取绑定成员的地址 功能。

        总而言之,你应该使用模板和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;
        }
        

        【讨论】:

          猜你喜欢
          • 2021-10-12
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-09-27
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多