5

我在处理指向 C++ 中重载成员函数的指针时遇到了一个小问题。以下代码编译良好:

class Foo {
public:
    float X() const;
    void X(const float x);
    float Y() const;
    void Y(const float y);
};

void (Foo::*func)(const float) = &Foo::X;

但这不能编译(编译器抱怨重载不明确):

void (Foo::*func)(const float) = (someCondition ? &Foo::X : &Foo::Y);

大概这与编译器将条件运算符的返回值与函数指针类型分开排序有关?我可以解决它,但我很想知道规范如何说所有这些都应该起作用,因为它看起来有点不直观,如果有一些方法可以解决它而不会退回到 5 行 if-then-else .

我正在使用 MSVC++,如果这有什么不同的话。

谢谢!

4

3 回答 3

7

从第 13.4/1 节(“重载函数的地址,”[over.over]):

使用不带参数的重载函数名称在某些上下文中被解析为函数、指向函数的指针或指向重载集中特定函数的成员函数的指针。函数模板名称被认为是在此类上下文中命名一组重载函数。所选函数的类型与上下文中所需的目标类型相匹配。目标可以是

  • 正在初始化的对象或引用(8.5、8.5.3),
  • 作业的左侧(5.17),
  • 函数的参数(5.2.2),
  • 用户定义运算符 (13.5) 的参数,
  • 函数、运算符函数或转换 (6.6.3) 的返回值,或
  • 显式类型转换(5.2.3、5.2.9、5.4)。

重载函数名称前面可以有&运算符。重载的函数名不能在没有列出的上下文中使用而没有参数。[注意:重载函数名周围的任何冗余括号集都将被忽略(5.1)。]

您希望从上面的列表中选择的目标是第一个,一个正在初始化的对象。但是有一个条件运算符,条件运算符根据它们的操作数确定它们的类型,而不是根据任何目标类型。

由于显式类型转换包含在目标列表中,因此您可以分别对条件表达式中的每个成员指针表达式进行类型转换。我会先做一个typedef:

typedef void (Foo::* float_func)(const float);
float_func func = (someCondition ? float_func(&Foo::X) : float_func(&Foo::Y));
于 2009-09-14T23:02:03.413 回答
1

例子:

class Foo {
public:
    void X(float x) {}
    void Y(float y)  {}
    float X() const;
};
typedef void (Foo::*Fff)(float);
Fff func = &Foo::X;
Fff func2 = true ? (Fff)&Foo::X : (Fff)&Foo::Y;

int main(){
    return 0;
}

您需要立即强制转换 &Foo::X 以解决重载问题。请注意,如果您注释掉重载的 float X(),则不需要这样做。

看起来编译器不够聪明,无法推断出三元表达式所需的返回类型(这可能是一个错误)。

于 2009-09-14T22:51:58.633 回答
1

尝试:

    void (Foo::*func1)(const float) = &Foo::X;
    void (Foo::*func2)(const float) = &Foo::Y;

    void (Foo::*func3)(const float) = (someCondition ? func1:func2);

问题是三元运算符的结果类型是由它的参数决定的。
在这种情况下,它无法确定结果类型,因为输入类型有多个选项。直到确定了三元运算符的类型,它才会尝试赋值。

于 2009-09-14T23:05:05.747 回答