成员函数的函数签名是什么?

Zeb*_*ish 13 c++ pointers function

我无法理解函数签名和指针.

struct myStruct
{
    static void staticFunc(){};
    void nonstaticFunc(){};
};

int main()
{
    void (*p)();     // Pointer to function with signature void();
    p = &myStruct::staticFunc;    // Works fine
    p = &myStruct::nonstaticFunc; // Type mismatch   
}
Run Code Online (Sandbox Code Playgroud)

我的编译器说类型myStruct::nonstaticFunc()是void (myStruct::*)(),但不是指向它的指针类型?

我问,因为当你创建一个std::function对象时,你传递了你想要它指向的函数的函数签名,比如:

std::function<void()> funcPtr;      // Pointer to function with signature void()
not 
std::function<void(*)()> funcPtr;
Run Code Online (Sandbox Code Playgroud)

如果我不得不根据void()我会说的模式猜测:

void myStruct::();
or
void (myStruct::)();
Run Code Online (Sandbox Code Playgroud)

但这不对.我不明白为什么我应该添加一个星号,因为它是非静态的而不是静态的.换句话说,指针void(* )()指向带签名的函数void(),而指针void(myStruct::*)()指向带签名的函数是什么?

650*_*502 12

对我而言,似乎存在对成员指针的基本误解.例如,如果你有:

struct P2d {
    double x, y;
};
Run Code Online (Sandbox Code Playgroud)

成员指针double P2d::*mp = &P2d::x;不能指向特定实例的x坐标,而是指向名称的"指针" :要获得双倍,您需要提供您正在寻找的实例...例如: P2dxP2d

P2d p{10, 20};

printf("%.18g\n", p.*mp); // prints 10
Run Code Online (Sandbox Code Playgroud)

这同样适用于成员函数......例如:

struct P2d {
    double x, y;
    double len() const {
        return sqrt(x*x + y*y);
    }
};

double (P2d::*f)() const = &P2d::len;
Run Code Online (Sandbox Code Playgroud)

where f不是指向特定实例的成员函数的指针,它需要this调用

printf("%.18g\n", (p.*f)());
Run Code Online (Sandbox Code Playgroud)

f换句话说,它只是一个"选择器",它的哪个const成员函数P2d接受没有参数并返回double你感兴趣的类.在这种特定情况下(因为只有一个成员函数兼容),这样的选择器可以使用零位存储(您可以设置该指针唯一可能的值&P2d::len).

请不要因为不了解会员指针而感到羞耻.它们确实有点"奇怪",并没有多少C++程序员理解它们.

说实话,它们也没那么有用:最常用的是指向特定实例的方法指针.

C++ 11提供了std::function包装器和lambdas:

std::function<double()> g = [&](){ return p.len(); };

printf("%.18g\n", g()); // calls .len() on instance p
Run Code Online (Sandbox Code Playgroud)


Sto*_*ica 5

std::function<void()> funcPtr = std::bind(&myStruct::nonstaticFunc, obj);
Run Code Online (Sandbox Code Playgroud)

是如何在中存储成员函数std::function。成员函数必须在有效对象上调用。


如果要将对象的传递延迟到以后,则可以这样完成:

#include <functional>
#include <iostream>

struct A {

    void foo() { std::cout << "A::foo\n"; }
};

int main() {
    using namespace std::placeholders;

    std::function<void(A&)> f = std::bind(&A::foo, _1);

    A a;
    f(a);

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

std::bind将为您处理细节。std::function仍然必须具有常规函数的签名作为其类型参数。但是,如果使对象显示为函数的参数,则它可以掩盖成员。


附件
对于分配给std::functionstd::bind只要原型是正确的,您甚至不需要后期绑定该对象:

std::function<void(A&)> f = &A::foo;
Run Code Online (Sandbox Code Playgroud)

  • `std :: function &lt;void(A&)&gt; f =&A :: foo;`应该也可以正常工作,而无需绑定。它已经将`&A :: foo`视为“可以通过`A`来调用的东西”。 (5认同)