指向成员函数的指针奇怪
Pointer to member function weirdness
我想做一些绑定与我的c++代码,并使用指针到成员函数。
我有以下代码:
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),编译器认为这两行都是ok的(!)
是编译器错误吗?
在不修改类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)'
我认为这是一个bug。c++ 11标准第13.4/1段:
使用没有实参的重载函数名在某些上下文中被解析为函数A指向函数的指针或指向成员函数的重载集中特定函数的指针。[…]。选择的函数类型与上下文中所要求的目标类型的函数类型相同的。[…目标可以是
—对象或引用被初始化(8.5,8.5.3),
—赋值操作(5.17)的左侧,
——函数的形参(5.2.2),
—用户定义操作符(13.5)的形参,
—函数、操作符函数或转换(6.6.3)的返回值,
- 一个显式的类型转换(5.2.3 5.2.9, 5.4),或
—非类型模板形参(14.3.2)。
由于重载集中哪个成员函数的签名与显式将其强制转换为的成员函数的签名相同,因此您的代码是合法的。
除此之外,你的代码在Clang 3.2, GCC 4.7.2, GCC 4.8, ICC 13.0.1和(!)用于。请看下面的例子:
编辑:你发布的新代码确实是非法的。
第二次强制转换无法解析,因为setA()
成员函数中没有一个只接受一个 float形参。因此,编译器不知道表达式&B::setA
指的是哪个函数。通常,它会尝试基于上下文显式转换来消除歧义,但这没有帮助,因为它指定了一个与setA()
的两个重载的签名不兼容的签名。
如果你想知道为什么会出现这种情况,为什么没有选择第二个重载,那么原因是带有默认实参的形参仍然是函数的形式形参(即使在某些调用中可以省略它),并且它的类型仍然算作函数签名的一部分。
另一方面,默认实参不是函数签名的一部分:1.3.20 [defns.signature.member]
<class member function>
名称,参数类型列表(8.3.5),函数所属的类,cv-qualifiers(如有)和ref-qualifier(如有)
现在,如果去掉重载setA(A)
,编译器不知道表达式&B::setA
引用的是哪个成员函数,因为只有一个。不需要使用显式强制转换来解析表达式。
然后,由于函数指针可以强制转换为其他类型的函数指针,编译器执行额外的转换到指定的目标类型
- 如何正确编写指针函数声明?
- C++常规指针函数或模板
- 如何重新定义 C++ 指针函数?
- C++ 指向其他类函数的指针函数
- 指针到指针函数参数
- 将指向成员的指针函数传递到模板中
- C++ 在 none 常量指针函数中返回一个常量指针
- 如何使用指针函数编写/读取数组
- 是C 中的函数指针函数对象
- 如何从另一个类调用指向成员的指针函数
- 如何声明采用指向成员的指针函数的函数
- 如何构造一个以可变参数指针函数作为成员的类?
- c 通过值或指针函数语法
- 将typedef方法作为指针函数传递
- 从 Main 中的双指针函数打印出指针数组
- strcpy 对指针函数的引用
- 这是否仍然声明一种指针函数的别名?
- 将指向成员的指针函数与 std::shared_ptr 结合使用
- 'Incomplete type' 为标准::函数声明指向成员的指针函数模板参数时出错
- 从注入进程的 DLL 调用函数并更改指针函数的地址