hil*_*sia 10 c++ operators overload-resolution
我发现C++解析运算符重载的奇怪行为,我无法解释自己.指向描述它的某个资源的指针就像答案一样好.
我有2个翻译单位.在一个(称为util.cpp/h)中,我声明并定义了两个运算符(我省略了readabilty的实际实现,无论如何都会发生problam):
// 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
Run Code Online (Sandbox Code Playgroud)
和:
//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;
}
Run Code Online (Sandbox Code Playgroud)
如果在全局命名空间中,这些运算符是因为它们在std类型和内置类型上运行,并且应该可以在任何地方使用.它们只能从全局命名空间(例如来自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
Run Code Online (Sandbox Code Playgroud)
和:
//test.cpp
#include "test.h"
#include "util.h"
#include <iostream>
void Namespace::SomeClass::test(std::istream& is) {
::operator>>(is, "c"); //works
is >> "c" //fails
}
Run Code Online (Sandbox Code Playgroud)
为什么编译器在命名空间中没有operator >>但是找不到时会找到正确的运算符?为什么运算符会影响编译器找到正确的编译器的能力,即使它具有不同的签名?
解决这个问题的一个尝试是
std :: istream&operator >>(std :: istream&is,const char*str){:: operator >>(is,str); }
进入命名空间,但链接器抱怨以前的定义.附加:为什么链接器会找到编译器找不到的东西?
jpa*_*cek 10
这是一个隐藏名称的问题.标准说(c ++ 03,3.3.7/1)
名称可以通过嵌套声明性区域或派生类(10.2)中相同名称的显式声明来隐藏.
您的案例中的"名称"将是operator>>,名称空间构成嵌套的声明性区域.
解决这个问题的最简单方法是使用using声明namespace-local的声明operator<<:
namespace your_namespece {
std::istream& operator>>(std::istream& is, SomeClass& obj) { return is; };
using ::operator>>;
}
Run Code Online (Sandbox Code Playgroud)
请注意,此功能不会干扰Koenig查找(至少在您的情况下,原则上它可以),因此std::仍将找到IO运算符.
PS:另一种解决此问题的可能性是将运算符定义SomeClass为内联friend.这些函数在命名空间级别(在"他们的"类之外)声明,但从那里看不到.它们只能通过Koenig查找找到.
| 归档时间: |
|
| 查看次数: |
3564 次 |
| 最近记录: |