在谷歌C++风格指南,还有对Operator Overloading一节,有一个奇怪的说法:“你不能转发重载运算符&的声明类”?
超载也有令人惊讶的 后果。例如,您不能 正向声明的类重载
operator&
。
这看起来不正确,我一直没能找到任何导致GCC出现问题的代码。有谁知道这个声明是指什么?
在谷歌C++风格指南,还有对Operator Overloading一节,有一个奇怪的说法:“你不能转发重载运算符&的声明类”?
超载也有令人惊讶的 后果。例如,您不能 正向声明的类重载
operator&
。
这看起来不正确,我一直没能找到任何导致GCC出现问题的代码。有谁知道这个声明是指什么?
5.3。1的标准是“可以采用不完整类型的对象的地址,但是如果该对象的完整类型是声明运算符&()作为成员函数的类类型,那么行为是未定义的(并且没有诊断是必须的)。”
我也不知道这一点,但正如另一张海报指出的,很容易看出它如何导致编译器生成不正确的代码。
编辑占到评论:
这是一个猜测,但主要的原因转发声明一个是能够指针声明为该类。编译器必须在定义之前对类进行假设 - 例如指针的大小。
是否可以通过重载运算符&来更改T *的大小? (编辑:评论员 - 我想不是) - 但
什么假设是由超载运算符违反& - 它如何改变类?
这是一种方法。
我可以这样写:
class A;
void f(A& x) {
A* xPointer = &x;
}
具有新的意义,如果运营商&()过载比,如果没有,编译器可能认为它可以为它生成代码,但它是错误的。
我没有听说过,要么,但在此之前给了潜在的混乱结果相同的代码和超负荷后:
#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或很多通用的代码搭配使用。
我认为这个陈述并不准确。像其他答案一样,我在这里猜测。首先,我假设他们指的是unary operator& and not binary operator&。那就是:
int x = 5;
int* p = &x; // unary &
if (x & 1) // binary &
你可以转发声明你想要的任何类。但是,如果类重载一元运算符&,并且您在指向其中一个对象的指针上调用一元运算符&,则可能会出现不一致的行为(有时您只需获取地址,有时您会调用重载的方法)。这很容易变成几乎无法调试的东西。
我很高兴fizzer实际上看着标准,并不只是猜测。
措辞不明确,你当然可以提前申报班级 - 但是显然,这个规则采取了“不应该”的立场,即班级超载operator&
。
其他编码标准中也存在类似规则,例如JSF(pdf)规则159规定operator&
不应重载。
由于能够重载运算符&,因此提升库提供了handy template addressof()以负责查找类的实际地址。不是我建议你超载运算符&,但如果需要,可以获得帮助。
无论如何,指针的大小都是一样的,不是吗? – 2008-10-06 23:11:34
我相信指针总是相同的大小(这就是为什么编译器可以承担的大小..),除了成员函数指针的情况下,无论如何,这些指针并不是传统意义上的“指针”。 – 2008-10-06 23:14:14
是的,我认为是这样 - 我只是试图从一个前提开始,即声明一个类型的前置点,以便编译器可以在没有完整声明的情况下开始对其进行一些假设。运营商违反了什么假设。 – 2008-10-06 23:14:53