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

时间:2016-12-26 06:35:08

标签: c++ function pointers

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

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   
}

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

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

std::function<void()> funcPtr;      // Pointer to function with signature void()
not 
std::function<void(*)()> funcPtr;

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

void myStruct::();
or
void (myStruct::)();

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

5 个答案:

答案 0 :(得分:11)

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

struct P2d {
    double x, y;
};

成员指针double P2d::*mp = &P2d::x;无法指向特定 x实例的P2d坐标,而是指向名称{{的“指针” 1}}:要获得双倍,您需要提供您正在寻找的x实例...例如:

P2d

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

P2d p{10, 20};

printf("%.18g\n", p.*mp); // prints 10

其中struct P2d { double x, y; double len() const { return sqrt(x*x + y*y); } }; double (P2d::*f)() const = &P2d::len; 不是指向特定实例的成员函数的指针,需要使用

调用f
this
换句话说,

printf("%.18g\n", (p.*f)()); 只是的一个“选择器”,类f的哪些const成员函数不接受任何参数并返回您感兴趣的P2d < / strong>即可。在这种特定情况下(因为只有一个成员函数兼容),这样的选择器可以使用零位存储(唯一可能的值,您可以将指针设置为double)。

首先,不要因为不理解成员指针而感到羞耻。它们确实有点“奇怪”,并没有很多C ++程序员理解它们。

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

C ++ 11提供了&P2d::len包装器和lambdas:

std::function

答案 1 :(得分:4)

var allKeys = {};

db.YOURCOLLECTION.find().forEach(function(doc){Object.keys(doc).forEach(function(key){allKeys[key]=1})});

allKeys;

您是如何在std::function<void()> funcPtr = std::bind(&myStruct::nonstaticFunc, obj); 中存储成员函数的。必须在有效对象上调用成员函数。

如果你想延迟一个对象的传递直到以后,你可以这样做:

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; } 将为您处理细节。 std::bind仍然必须具有常规函数的签名作为其类型参数。但是,如果使对象显示为函数的参数,它可以屏蔽成员。

Addenum
要分配到std::function,您甚至不需要std::function来对象的后期绑定,只要原型是正确的:

std::bind

答案 2 :(得分:1)

p = &myStruct::staticFunc;    // Works fine
p = &myStruct::nonstaticFunc; // Type mismatch

原因:函数到指针的转换从不适用非静态成员函数,因为引用非静态成员函数的左值 无法获得。

  

指针void(*)()指向带有签名void()的函数,而指针void(myStruct :: *)()指向带签名的函数是什么?

myStruct::是为了确保调用struct myStruct非静态成员函数(而不是其他结构,如下所示):

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

int main()
{
    void (*p)();     // Pointer to function with signature void();
    void (myStruct::*f)();
    p = &myStruct::staticFunc;    // Works fine
    p = &myStruct2::staticFunc;   // Works fine
    f = &myStruct::nonstaticFunc; // Works fine
    //f =  &myStruct2::nonstaticFunc;  // Error. Cannot convert 'void (myStruct2::*)()' to 'void (myStruct::*)()' in assignment

    return 0;
}

答案 3 :(得分:0)

当你使用指针,std :: function或std :: bind来引用非静态成员函数(即&#34;方法&#34;类Foo)时,第一个参数必须是具体的类Foo的对象,因为非静态方法必须由具体对象调用,而不是由Class。

调用

更多详情:std::functionstd::bind

答案 4 :(得分:0)

答案在doc

  

指向成员声明者的指针:声明S C::* D;声明D为   指向由C确定的类型的非静态成员的指针   decl-specifier-seq S

struct C
{
    void f(int n) { std::cout << n << '\n'; }
};

int main()
{
    void (C::* p)(int) = &C::f; // pointer to member function f of class C
    C c;
    (c.*p)(1);                  // prints 1
    C* cp = &c;
    (cp->*p)(2);                // prints 2
}

没有签名void ()的功能。函数void (*)()void (foo::*)()方法foo。星号是必需的,因为它是指向x的指针。 std::function与此无关。

注意:您的疑惑是void()void (*)()的签名相同。甚至int()&lt; =&gt; int (*)()。也许你认为你可以用int (foo::*)来写一个方法指针。但这是一个数据成员指针,因为括号是可选的,int (foo::*)&lt; =&gt; int foo::*

要避免这种模糊的语法,您需要使用返回类型,星号及其参数编写指向function / member的指针。