【问题标题】:Type conversion error in pointer to class member function指向类成员函数的指针中的类型转换错误
【发布时间】:2018-07-17 18:31:46
【问题描述】:

您好,这是this previous question i did的更新

我试图通过类中的指针执行一个函数(类内容与我遇到的问题无关)。

这是上一个问题中发布的代码:

错误信息:

cannot convert ‘Clip::func’ from type ‘void (Clip::)(std::string) {aka void (Clip::)(std::basic_string<char>)}’ to type ‘callback {aka void (*)(std::basic_string<char>)}’

剪辑.h

void func(string str){
    cout << str << endl;
}

剪辑.cpp

void Clip::update(){
    typedef void(*callback)(string);
    callback callbackFunction = func;
    callbackFunction("called");
}

-----我找到的解决方案------


我和一个朋友做了一些快速研究以找到解决这种情况的方法,这就是我们发现的。尽管这可行,但我们对所涉及的表达式有一些疑问(帖子末尾的问题)

剪辑.h

    typedef  void (Clip::*Callback) (string);
    void func(string _val);

剪辑.cpp

void Clip::update(){
    Callback function;
    function = &Clip::func;
    (this->*function)("a");
}

问题:

a- 在上一篇文章中@tkausl 回答:“...成员函数指针与(非成员)函数指针不兼容”。这就是其他代码在任何类中都不起作用的原因(即使该类完全为空)?

b- 如果我们已经在 Clip 类中,为什么还要像这样声明指针:Clip::*Callback

c- 这个表达式是什么意思?:this->*function

d- 是否有更简单的方法或表达方式来满足同样的要求?

提前致谢。

【问题讨论】:

  • 我感觉你还没有掌握成员函数指针和普通函数指针的区别。请记住,非静态成员函数 需要 和要调用的实例。你不能调用Clip::func,就像你不能将Clip::func分配给void(*)(string)一样。它会在哪个实例上调用它?
  • This question 听起来像是重复的,但我并不是你真正要问的。

标签: c++ class pointers function-pointers class-members


【解决方案1】:

您确实遇到过pointers to member functions。它们与普通函数指针相似,但更细微,因为(非静态)成员函数总是隐式地传递一个特殊的 this 参数,该参数引用函数所在的当前对象被调用。该秘密this 参数是根据包含该函数的类进行强类型化的。这就是为什么类名也是指向成员函数类型的指针的一部分。这也是它们不与常规函数指针混合的原因。这是一个基本示例:

// Declaration of a pointer to member function
// Note that no object is used here
void (ClassName::*my_fn_pointer)(ParameterTypes);

// Assignment also doesn't use an object
my_pointer = &ClassName::exampleMemberFunction;

// But to invoke the method, you need an object
ClassName obj;
(obj::*my_fn_pointer)(example_params);

// Alternatively, inside a member function of ClassName:
(this->*my_fn_pointer)(example_params);

有很多选择。我看不到您的其余代码以及您要解决的问题,因此我的建议有限。但是,我赞成将std::functionlambdas 一起使用:

// std::function generically wraps a callable type
std::function<void(ParamTypes)> my_fn;


// Using an object:
ClassName obj;
// lambda declaration
my_fn = [&obj](ParamTypes params){
    // 'obj' is captured by reference, so make sure it stays alive as long as needed
    obj.chooseYourMemberFunctionHere(params);
};

// function is called here, syntax is easier on the eyes
my_fn(example_params);


// Using 'this' inside a member function:
my_fn = [this](ParamTypes params){
    // 'this' is captured by reference
    // also make sure the current object stays alive alive as long as needed
    this->chooseYourMemberFunctionHere(params);
};

my_fn(example_params); // function is called here

【讨论】:

    【解决方案2】:

    一个

    这与您编写代码的位置无关。成员函数指针和函数指针是两种不同类型的指针。您的代码不起作用,因为您无法将成员函数指针分配给普通函数指针。如果可以考虑这段代码,它的输出应该是什么?

    class Foo
    {
    public:
        Foo(int x) :x(x) {}
        void bar(int y)
        {
            std::cout << x+y;
        }
        int x;
    }
    int main()
    {
        typedef void(*callback)();
    
        callback ptr = &Foo::bar;//Won't compile with same error as in your question
    
        ptr(5);
    }
    

    没有Foo 的实例,因此没有要打印的x。与 C# 不同,C++ 不会让您捕获 this,因此 Foo f; callback ptr = &amp;f::bar 也不会编译。你可以认为Foo::bar 相当于

    void bar(Foo* this,int y)
    {
       std::cout<< this->x+y;
    }
    

    现在您会发现这些函数类型确实不同。

    B

    您可以从上面的bar 翻译中看到this 的类型必须指定,无论您在哪里编写该代码都没有关系。

    C

    调用成员函数是通过-&gt;* 运算符完成的,它的左侧正是缺少的this 指针,右侧是成员函数指针变量和参数。见:

    Foo foo;
    typedef void(Foo::callback)(int);//Member pointer
    callback ptr = &Foo::bar;//Now OK
    Foo* thisFoo = &foo;//Left-hand side must be a pointer to Foo
    (thisFoo->*ptr)(5);//equivalent to foo->bar(5);
    

    this-&gt;*function只是调用存储在function变量中的成员函数,并使用this指针作为实例。

    D

    什么要求?无法进行转换。如果您知道每时每刻都只会为每种类型分配一个回调,那么模板函数和局部静态变量就有一种 hacky 方式。否则尽量不要使用它们,有更安全的 lambdas 和 std::function 可用替代品,可以以 c# 方式绑定 thislink

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-07-27
      • 2013-06-06
      • 1970-01-01
      • 2015-11-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多