C++ 什么';成员函数的函数签名是什么?

C++ 什么';成员函数的函数签名是什么?,c++,function,pointers,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::

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

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::nonstatifunc()
的类型是void
(myStruct::*)()
,但这不是指向它的指针的类型吗

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

std::function<void()> funcPtr;      // Pointer to function with signature void()
not 
std::function<void(*)()> funcPtr;
但这是不对的。我不明白为什么我应该添加星号,因为它是非静态的,而不是静态的。换句话说,指针
void(*)(
指向带有签名的函数
void()
,指针
void(myStruct::*)()
指向带有签名的函数什么

std::function<void()> funcPtr = std::bind(&myStruct::nonstaticFunc, obj);
std::bind
将为您处理详细信息
std::function
仍然必须具有常规函数的签名作为其类型参数。但是,如果使对象显示为函数的参数,则它可以屏蔽成员


加法:
对于分配到
std::function
,只要原型正确,对象的后期绑定甚至不需要
std::bind

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

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

更多详情:及 .

答案在

指向成员声明器的指针:声明
sc::*D声明
D
为 指向由确定类型的
C
的非静态成员的指针 decl说明符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
}
struct C
{

void f(int n){std::cout对我来说,似乎对成员指针是什么有一个基本的误解。例如,如果您有:

struct P2d {
    double x, y;
};
成员指针
double P2d::*mp=&P2d::x;
不能指向特定的
P2d
实例的
x
坐标,而是指向名称
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;
这同样适用于成员函数……例如:

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
换句话说,它只是
P2d
的常量成员函数中的一个“选择器”,不接受任何参数并返回您感兴趣的
double
。在这种特定情况下(因为只有一个成员函数兼容),这样的选择器可以使用零位存储(您可以设置该指针的唯一可能值是
&P2d::len

请不要因为不理解成员指针而感到羞愧。它们确实有点“奇怪”,而且没有多少C++程序员理解它们。 老实说,它们也不是很有用:最需要的是指向特定实例的方法的指针

C++11提供了
std::function
wrapper和lambdas:

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

printf("%.18g\n", g()); // calls .len() on instance p
std::函数g=[&](){返回p.len();};
printf(“%.18g\n”,g());//在实例p上调用.len()
原因:函数到指针的转换从不应用于非静态成员函数,因为引用非静态成员函数的左值 无法获取


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

std::function<void()> funcPtr = std::bind(&myStruct::nonstaticFunc, obj);
myStruct::
是为了确保调用struct
myStruct
的非静态成员函数(而不是其他结构,如下所示):


如果不将成员函数绑定到类对象,则无法在
std::function
中保存成员函数。指向成员的指针与常规函数指针不同。不能直接将成员函数分配给
std::function
,您需要绑定它。我知道如何指向非静态成员函数,我只需声明void(myStruct::*)()但是,我想知道它的签名是什么,因为VoIP(*)()所指向的函数的签名是VoID())TeNoNeMeRice——如果您只想存储一个成员函数以供以后使用,请参阅我的Eddio.C++没有任何特定的签名格式。(8.3.5),函数是其成员的类,cvqualifiers(如果有)和ref限定符(如果有)。注意签名包括名称。对,那么签名是什么?指针void()指向函数签名void(),指针void(myStruct::)()指向函数签名什么?我以为这样一个函数的签名是void(),这就是为什么您可以声明:void afuntakingafunc(void());
std::function f=&A::foo;
应该也可以工作,而无需
bind
。它已经将
&A::foo
视为“如果传递了
A
则可以调用的东西”@hvd-图我应该把它加进去。谢谢。我一直忘了在每一个新的标准版本中,bind的使用越来越少。据我所知,非静态成员函数不同于成员变量。obj1.intMemb的地址与obj2.intMemb的地址不同,但obj1.membFunc对所有对象都有相同的地址对象,甚至我认为是虚拟的。它就像一个带this指针的普通静态函数,这种语言强制你通过一个对象调用它,所以它保证得到“this”对象的地址。它可能不允许你将它赋给void*p,因为你不能像p()那样调用它;但我不明白为什么不能像…@TitoneMaurice那样调用它:非静态成员指针不是内存地址;在本例中,数据指针不是内存地址
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;
}