【发布时间】:2012-07-06 18:09:34
【问题描述】:
我发现 C++ 解析运算符重载的奇怪行为,我无法解释自己。指向一些描述它的资源的指针和答案一样好。
我有 2 个翻译单元。在一个(称为 util.cpp/h)中,我声明并定义了两个运算符(为了便于阅读,我省略了真正的实现,无论如何都会出现问题):
// util.h
#ifndef GUARD_UTIL
#define GUARD_UTIL
#include <iostream>
std::istream& operator>>(std::istream& is, const char* str);
std::istream& operator>>(std::istream& is, char* str);
#endif
还有:
//util.cpp
#include "util.h"
#include <iostream>
std::istream& operator>>(std::istream& is, const char* str) {
return is;
}
std::istream& operator>>(std::istream& is, char* str) {
return is;
}
这些运算符当然是在全局命名空间中,因为它们对标准类型和内置类型进行操作,并且应该可以在任何地方使用。它们可以在全局命名空间(例如从 main())中正常工作,或者明确告诉编译器它们在全局命名空间中(参见代码示例)。
在另一个翻译单元(称为 test.cpp/h)中,我在命名空间中使用这些运算符。在我将类似的运算符放入此命名空间之前,此方法有效。一旦添加此运算符,编译器(例如 gcc 或 clang)就无法再找到可行的运算符>>。
// test.h
#ifndef GUARD_TEST
#define GUARD_TEST
#include <iostream>
namespace Namespace {
class SomeClass {
public:
void test(std::istream& is);
};
// without the following line everything compiles just fine
std::istream& operator>>(std::istream& is, SomeClass& obj) { return is; };
}
#endif
还有:
//test.cpp
#include "test.h"
#include "util.h"
#include <iostream>
void Namespace::SomeClass::test(std::istream& is) {
::operator>>(is, "c"); //works
is >> "c" //fails
}
为什么在 Namespace 中没有 operator>> 时编译器能找到正确的 operator>> 但有一个时却找不到?为什么操作符会影响编译器找到正确的能力,即使它有不同的签名?
解决此问题的一种尝试是放置
std::istream& 运算符>>(std::istream& is, const char* str) { ::operator>>(is, str); }
进入命名空间,但链接器抱怨以前的定义。所以附加:为什么链接器可以找到编译器找不到的东西?
【问题讨论】:
-
您是否尝试过将 Namespace::operator >> 声明为“内联”
-
顺便说一句,您的班级声明后缺少
; -
添加了 ;.这是我常犯的错误……
-
@bert-jan 不,因为在我的实际实现中,输入流是用一些代码解析的,我发现很多代码需要内联。
标签: c++ operators overload-resolution