“你不能转发声明重载运算符和类的类”?

时间:2008-10-06 23:00:55

标签: c++ gcc

在Google C ++样式指南中,有Operator Overloading部分有一个奇怪的陈述:

  

重载也令人惊讶   后果。例如,你不能   forward声明重载的类   operator&

这似乎不正确,我无法找到任何导致GCC出现问题的代码。有谁知道那句话是指什么?

6 个答案:

答案 0 :(得分:20)

5.3.1标准具有“可以采用不完整类型的对象的地址,但如果该对象的完整类型是声明operator&()作为成员函数的类类型,那么行为是未定义(并且不需要诊断)。“

我也不知道这一点,但正如另一张海报所指出的那样,很容易看出它如何导致编译器生成错误的代码。

答案 1 :(得分:16)

我也没有听说过,但这会在重载之前和之后为相同的代码提供可能令人困惑的结果:

#include <iostream>

class Foo;

void bar (Foo& foo) {
    std::cout << &foo << std::endl;
}

class Foo {
public:
    bool operator & () { return true; }
};

void baz (Foo& foo) {
    std::cout << &foo << std::endl;
}

int main () {
    Foo foo;

    bar(foo);
    baz(foo);

    return 0;
}

输出:

0x7fff092c55df
1

尽管还有其他原因导致你不这样做 - 重载地址 - 不能很好地与stl或更通用的代码一起使用。

答案 2 :(得分:6)

我认为这句话并不准确。和其他答案一样,我猜这里。首先,我假设他们指的是unary operator& and not binary operator&。那就是:

int x = 5;
int* p = &x; // unary &
if (x & 1)   // binary &

您可以转发声明您想要的任何课程。但是,如果该类超载一元运算符&amp;,并且您调用一元运算符&amp;在指向其中一个对象的指针上,您可能会得到不一致的行为(有时您只是获取地址,有时您会调用重载方法)。这很容易变成几乎无法调试的东西。


我很高兴fizzer实际上看了标准并且不仅仅是猜测。

答案 3 :(得分:1)

由于能够超载操作员和boost库提供handy template addressof()来处理查找类的真实地址。并不是说我建议你重载operator&amp;,但如果你需要,可以提供帮助。

答案 4 :(得分:0)

编辑注释:

这是猜测,但转发声明的主要原因之一是能够声明指向该类的指针。在得到定义之前,编译器必须对类进行假设 - 例如,指针的大小。

是否可以通过重载运算符来改变T *的大小。换一个T? (编辑:评论员 - 我认为不是) - 但

重载运算符&amp ;;违反了什么假设 - 它如何改变课程?

这是一种方式。

我可以写:

class A;

void f(A& x) {
    A* xPointer = &x;
}

如果operator&amp;()重载,那么它有一个新的意义,编译器可能认为它可以为它生成代码,但这是错误的。

答案 5 :(得分:0)

措辞不清楚,你当然可以向前宣布这个类 - 但是规则显然是采取你不应该在类重载operator&的位置。

其他编码标准中也存在类似的规则,例如JSF(pdf)规则159规定operator&不应过载。