【问题标题】:Pointer to a class method in c++ [duplicate]指向c ++中的类方法的指针[重复]
【发布时间】:2017-12-08 16:20:56
【问题描述】:

A 有很多 B 类,一个类 A 有一个对象 b。这个对象 b 有一个函数 (calc),它需要一个指向 A 对象中方法的指针。这个方法 (fun) 访问类中的私有变量(在我的示例中只返回 3)。

class A;

class B {
public:
  virtual int calc ( int (A::*fun)())  {    return 2*fun();  };
};

class A {
  B* b;

public:
  A (B* b_) : b (b_) {};
  int fun() { return 3; };
  int run(){ return b->calc(&A::fun); };
};

int main() {
  B* b = new B();
  A a(b);
  a.run();
  return 0;
}

如何在 B 类中 calc 方法的定义中正确使用指向方法的指针?

我收到此错误消息:

teste.cpp:10:58: error: must use ‘.*’ or ‘->*’ to call pointer-to-member     function in ‘fun (...)’, e.g. ‘(... ->* fun) (...)’
   virtual int calc ( int (A::*fun)())  {    return 2*fun();  };
                                                      ^

【问题讨论】:

  • 指向非静态成员函数的指针确实很有趣,但你不能像那样使用它们。我会调查 std::function
  • 为什么将 C 答案链接为 C++ 问题的副本?调用成员函数与调用 C 中的函数不同。
  • 我相信这是一个更好的复制stackoverflow.com/questions/12662891/…
  • 这是一个非常奇怪的重复。

标签: c++ function-pointers


【解决方案1】:

如果对您可行,我推荐std::function 方法。但是,为了完整起见,以下是正确使用指向成员函数的方法。

指向成员的指针本身不存储A 的“当前”实例,因此您需要显式传递它。然后使用特殊的->*(或.*)语法来调用它。

virtual int calc (A* value, int (A::*fun)())  {
  return 2 * (value->*fun)();
};

那么你可以称它为b->calc(this, &A::fun);

【讨论】:

    【解决方案2】:

    您可以按照自己的方式进行操作,但成员函数在特定实例上必须是 called

    class A;
    
    class B {
    public:
        virtual int calc(A* a, int (A::*fun)()) { return 2 * (a->*fun)(); };
    };
    
    class A {
        B* b;
    
    public:
        A(B* b_) : b(b_) {};
        int fun() { return 3; };
        int run() { return b->calc(this, &A::fun); }; // now also passing this pointer
    };
    
    int main() {
        B* b = new B();
        A a(b);
        a.run();
        return 0;
    }
    

    如果您可以在没有 calc() 虚拟的情况下生活,那么 lambda 也是一种选择:

    class A;
    
    class B {
    public:
        template<typename T>
        int calc(T fun) { return 2 * fun(); };
    };
    
    class A {
        B* b;
    
    public:
        A(B* b_) : b(b_) {};
        int fun() { return 3; };
        int run() {
            return b->calc([this]() {return fun(); } );
        };
    };
    
    int main() {
        B* b = new B();
        A a(b);
        a.run();
        return 0;
    }
    

    【讨论】:

      【解决方案3】:

      一个指向类的方法被定义和初始化为(假设 SomeFn 匹配签名):

      RetType (ClassName::*pfn)(Args) = &ClassName::SomeFn;
      

      并被称为:

      ClassName * ptr = GetClassPtr();
      (ptr->*pfn)(arg, arg);
      

      【讨论】:

        【解决方案4】:

        如果你能够使用 C++11,那么你应该使用 std::functionstd::bind:否则你需要使用 pointer to member function + 指向实例的指针。

        使用 C++11

        #include <functional>
        
        class B {
        public:
          virtual int calc (std::function<int()>&& fun) { return 2 * fun();  }; };
        };
        
        class A {
          B* b;
        
        public:
          A (B* b_) : b (b_) {};
          int fun() { return 3; };
          int run() { return b->calc(std::bind(&A::fun, this)); };
        };
        

        没有 C++11

        class B {
        public:
          virtual int calc (int(A::*fnptr)(), A* a) { return 2 * (a->*fnptr)(); };
        };
        
        class A {
          B* b;
        
        public:
          A (B* b_) : b (b_) {};
          int fun() { return 3; };
          int run() { return b->calc(&A::fun, this); };
        };
        

        参见示例here

        【讨论】:

          猜你喜欢
          • 2010-09-08
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-10-11
          • 2010-12-05
          • 1970-01-01
          • 2013-08-07
          • 2019-10-23
          相关资源
          最近更新 更多