gpt4 book ai didi

c++ - 指向成员函数怪异的指针

转载 作者:太空宇宙 更新时间:2023-11-04 11:56:41 27 4
gpt4 key购买 nike

我正在尝试对我的 C++ 代码进行一些绑定(bind),并使用指向成员函数的指针。

我有以下代码:

class A
{
explicit A(float);
}
class B
{
void setA(A);
void setA(float);
}

然后我声明指向成员函数的指针:

(void (B::*)(A))&B::setA
(void (B::*)(float))&B::setA

编译器 (MSVC11) 发现第二行不明确。

如果我在类 B 中注释 setA(A),则编译器认为这两行都是正确的 (!)

这是编译器错误吗?

有没有办法在不修改 B 类签名的情况下规避这种情况?

编辑:

实际上,我发布的代码是从我的真实类中过度简化的,并且确实编译了..

这是一个真正重现错误的修改版本:

class A
{
public:
explicit A(float f=1.0f, float g=1.0f) {}
};
class B
{
public:
void setA(A){}
void setA(float f, float g=1.0f){}
};

(void (B::*)(A))&B::setA
(void (B::*)(float))&B::setA
(void (B::*)(float,float))&B::setA

第二行带来编译错误:错误 C2440:“类型转换”:无法将“重载函数”转换为“void (__thiscall B::*)(float)”

最佳答案

我会说这是一个错误。根据 C++11 标准的第 13.4/1 段:

A use of an overloaded function name without arguments is resolved in certain contexts to a function, a pointer to function or a pointer to member function for a specific function from the overload set. [...] . The function selected is the one whose type is identical to the function type of the target type required in the context. [...] The target can be

— an object or reference being initialized (8.5, 8.5.3),

— the left side of an assignment (5.17),

— a parameter of a function (5.2.2),

— a parameter of a user-defined operator (13.5),

— the return value of a function, operator function, or conversion (6.6.3),

an explicit type conversion (5.2.3, 5.2.9, 5.4), or

— a non-type template-parameter (14.3.2).

由于很清楚重载集中的哪个成员函数具有与您显式转换到的成员函数相同的签名,因此您的代码是合法的。

此外,您的代码可以在 Clang 3.2、GCC 4.7.2、GCC 4.8、ICC 13.0.1 和 (!) VC10 上正常编译。参见,例如,this live example .

编辑:

您发布的新代码确实是非法的。

无法解析第二个转换,因为没有一个成员函数 setA()只接受一个浮点参数。因此,编译器不知道表达式 &B::setA 指的是哪个函数。 .通常,它会尝试根据上下文显式转换来消除歧义,但这无济于事,因为它指定的签名与 setA() 的两个重载的签名不兼容。 .

如果您想知道为什么会这样以及为什么没有选择第二个重载,那么原因是带有默认参数的参数仍然是函数的形式参数(即使在某些调用中可以省略它) ),并且它的类型仍然算作函数签名的一部分。

另一方面,默认参数不是函数签名的一部分:

1.3.20 [defns.signature.member]

signature

<class member function> name, parameter type list (8.3.5), class of which the function is a member, cv-qualifiers (if any), and ref-qualifier (if any)

现在,如果您删除重载 setA(A) ,编译器确实知道表达式&B::setA是什么成员函数指,因为只有一个。无需使用显式转换来解析表达式。

然后,由于函数指针可以转换为其他类型的函数指针,因此编译器会执行额外的转换以指定目标类型。

关于c++ - 指向成员函数怪异的指针,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15959179/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com