【问题标题】:C++ invalid function type castingC++ 无效的函数类型转换
【发布时间】:2020-05-31 17:31:44
【问题描述】:

我已经阅读了有关此类问题的几个主题 - 但找不到简单而好的解决方案。代码如下:

void SomeFunction() { }

class A {
  public:
    typedef std::function<void(void)> AFunction;
    static void AMethod(AFunction f) { f(); }    
};

class B {
  public:    
    void B1Method() { }        
    void BCorrectCall() { A::AMethod(SomeFunction); }
    void BIncorrectCall() { A::AMethod(B1Method); }
};

问题在这里void BIncorrectCall() { A::AMethod(B1Method); },我收到有关无效转换的错误。实现这种行为的最简单方法是什么?非常感谢您的任何建议!

【问题讨论】:

  • Lambda 很棒,感谢大家,问题解决了。

标签: c++ pointer-to-member


【解决方案1】:

使用 lambda:

A::AMethod([this]{B1Method();});

在这种情况下没关系,但是如果你想存储AFunction f并在调用AMethod之后使用它,你必须确保B实例(其地址是保存在 lambda 中)只要你使用这个函数就说活着。

C++17 允许您 capture *this instead,这会将整个 B 实例复制到 lambda 中,但通常这不是您想要的。


你可以用 std::bind 做类似的事情(见另一个答案),但 lambdas 更灵活。

【讨论】:

    【解决方案2】:

    B1Method 不是void(*)(void),而是void(B1::*)(void)

    你可以这样做

    void BIncorrectCall() { A::AMethod(std::bind(&B1::B1Method, this)); }
    };
    

    【讨论】:

      【解决方案3】:

      问题在于B::B1Method()B 中的非static 成员函数,因此需要在B 的实例上调用它。

      如果B1Method()的实现不使用B的任何非static数据成员并且它不调用B的任何其他非static成员函数,那么只需声明它因为static 将与您当前的BIncorrectCall() 实现一起使用,因为您将不再需要在B 的实例上调用B1Method()

      class B {
        public:    
          static void B1Method() { } // static now      
          void BCorrectCall() { A::AMethod(SomeFunction); }
          void BIncorrectCall() { A::AMethod(B1Method); } // no change
      };
      

      否则,无论何时您想调用B1::B1Method(),您都必须保留B 类型的对象。

      【讨论】:

        【解决方案4】:

        最简单的方法是使其成为static,因此没有this 对象,但如果您需要它(this 对象),您可以使用lambdas

        class B {
        public:
            void B1Method() { }
            void BCorrectCall() { A::AMethod(SomeFunction); }
            void BIncorrectCall() {
                std::function<void(void)> el = [&](){this->B1Method();};
                A::AMethod(el);
            }
        };
        

        【讨论】:

          【解决方案5】:

          问题在于“B1Method”不是一个简单的函数——它是一个类方法。这意味着当您调用 myB.B1Method() 时,实际上是在调用 'B1Method(&myB)',有效地将 this 指针作为隐藏参数传递 - 因此您无法在不指定的情况下将 M1Method 转换为 std::function它应该作用于哪个对象。

          一种可行的方法是使用 std::bind 从对象(类实例)和方法的组合中构造可调用对象。比如:

          void BNowCorrectCall() { A::AMethod(std::bind(&B::B1Method, this)); }
          

          【讨论】:

          • B1Method(&amp;myB) 是考虑成员函数的常用方式,但在语言定义中没有依据。这不是编写或调用成员函数的方式。特别是,指向成员函数的指针不是指向函数的指针;这是一个完全不同的野兽。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多