ostream插入操作符与其非成员重载之间的关系 [英] Relation between ostream insertion operator and its non-member overload
问题描述
int i = 0;
std :: cout<<一世;
1,非成员重载(两个参数,一个是ostream,另一个是操作数,say int)在std命名空间中定义。因此,如果使用命名空间std;
不存在,我没有办法看到非成员重载可以被调用。
2,如果相反,成员运算符(ostream的成员;一个参数,是操作数的类型,说int)function<的ostream被调用,我会期望像: std :: cout.operator<<
那么,两者之间的关系究竟是什么呢?
问题扩展:如果我想重载插入操作符,使 std :: cout < my_obj;
工程(假设my_obj是用户定义类型的实例MyType),应该是
a)<$ c $流动&运算符<< MyType obj);
或
b)in MyType:
class MyType
{
...
ostream& ;运算符<< (MyType);
};
选项b)有效吗?它甚至有意义(我记得看到它在某个地方...)?选项a)和选项a)之间的关系是什么? b)
$ b
EDIT MAR 27 b
根据ecatmur的请求,这里有两个重载,具有相同的签名,但在不同的命名空间。使用gcc 4.9.2: http://melpon.org/wandbox/
#include< iostream>
namespace MyNameSpace
{
class MyType
{};
//签名可以在这里找到:http://www.cplusplus.com/reference/ostream/ostream/operator-free/
std :: ostream& operator<<<(std :: ostream& out,char ch)
{
out< std is doomed\\\
;
return out;
}
std :: ostream& operator<<<(std :: ostream& out,MyType t)
{
out< std is super doomed\;
return out;
}
}
int main()
{
MyNameSpace :: MyType t;
std :: cout<< t; // ... super doomed; ADL正按预期工作。
std :: cout<< 't'; // t;这证明当有两个具有相同签名但在不同命名空间中的运算符重载时,没有编译错误。 gcc默认为std。
return 0;
}
思考的是字符数据和 std :: string
等。;则可通过 参数相关查找 。你可以为 std :: cout.operator<<(i) / basic_ostream / operator_ltltrel =nofollow>其中 ostream
具有成员运算符<<
对于你自己的类型,你想到一个(非成员)朋友运算符<<
,这对于模板类( Barton-Nackman trick )或者运算符<<
访问通过访问器无法访问的数据:
code> class MyType
{
...
friend std :: ostream&运算符<< (std :: ostream&,MyType obj){...}
};
您建议的签名将允许您写 my_obj< my_obj
,这是不太可能有什么意义。
int i=0;
std::cout << i;
1, The non-member overload(two arguments, one being ostream& the other being type of operand, say int) is defined in std namespace. So if using namespace std;
is not present, there's no way I see that the non-member overload can be called.
2, If instead, the member operator(member of ostream; one argument, being the type of operand, say int) function << of ostream is called, I'd expect something like: std::cout.operator<< i;
--- isn't this rediculous?
So, what on earth is the relation between the two?
Question extended: if I want to overload the insertion operator so that std::cout << my_obj;
works(assume my_obj is the instance of a user-defined type, MyType), should I do
a) ostream& operator<< (ostream& os, MyType obj);
in the namespace of MyType
or
b) in MyType:
class MyType
{
...
ostream& operator<< (MyType);
};
does option b) ever work? Does it even make sense(I remember seeing it somewhere ...)? What's the relation between option a) & b)?
EDIT MAR 27
Upon the request from ecatmur, here're two overloads that have the same signature but in different namespaces. Using gcc 4.9.2: http://melpon.org/wandbox/
#include <iostream>
namespace MyNameSpace
{
class MyType
{};
// signature can be found here: http://www.cplusplus.com/reference/ostream/ostream/operator-free/
std::ostream& operator<<(std::ostream& out, char ch)
{
out << "std is doomed\n";
return out;
}
std::ostream& operator<<(std::ostream& out, MyType t)
{
out << "std is super doomed\n";
return out;
}
}
int main()
{
MyNameSpace::MyType t;
std::cout << t; // ... super doomed; ADL is working as intended.
std::cout << 't'; // t; this proves that when there're two operator overloads with the same signature but in different namespaces, there're no compilation errors. gcc defaults to the std one.
return 0;
}
The non-member overloads you're thinking of are those for character data and those for std::string
etc.; they're available via argument-dependent lookup. You can indeed write std::cout.operator<<(i)
for types where ostream
has a member operator<<
.
For your own types you're thinking of a (non-member) friend operator<<
, which can be particularly useful for template classes (the Barton-Nackman trick) or for those where the operator<<
accesses data not available via accessors:
class MyType
{
...
friend std::ostream& operator<< (std::ostream&, MyType obj) { ... }
};
Your proposed signature would allow you to write my_obj << my_obj
, which is unlikely to make much sense.
这篇关于ostream插入操作符与其非成员重载之间的关系的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!