ostream插入运算符与其非成员重载的关系
Relation between ostream insertion operator and its non-member overload
int i=0;
std::cout << i;
1,非成员重载(两个参数,一个是ostream,另一个是操作数类型,比如int)在std命名空间中定义。因此,如果 using namespace std;
不存在,我就无法看到可以调用非成员重载。
2,如果相反,调用 ostream 的成员运算符(ostream 的成员;一个参数,作为操作数的类型,比如 int)函数 <<,我希望是这样的:std::cout.operator<< i;
---这不是很可笑吗?
那么,这两者到底是什么关系呢?
扩展问题:如果我想重载插入运算符以便 std::cout << my_obj;
工作(假设 my_obj 是用户定义类型 MyType 的实例),我应该这样做吗
a) ostream& operator<< (ostream& os, MyType obj);
在 MyType
的命名空间中
或
b) 在 MyType 中:
class MyType
{
...
ostream& operator<< (MyType);
};
选项 b) 是否有效?它甚至有意义吗(我记得在某个地方看到过它......)?选项a)和b)有什么关系?
编辑 3 月 27 日
根据 ecatmur 的请求,这里有两个具有相同签名但位于不同名称空间中的重载。使用 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;
}
您想到的非成员重载是 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<<
。
对于您自己的类型,您正在考虑(非成员)friend operator<<
,这对于模板 类(Barton-Nackman trick)或那些operator<<
访问无法通过访问器获得的数据:
class MyType
{
...
friend std::ostream& operator<< (std::ostream&, MyType obj) { ... }
};
你提议的签名将允许你写 my_obj << my_obj
,这不太可能有多大意义。
int i=0;
std::cout << i;
1,非成员重载(两个参数,一个是ostream,另一个是操作数类型,比如int)在std命名空间中定义。因此,如果 using namespace std;
不存在,我就无法看到可以调用非成员重载。
2,如果相反,调用 ostream 的成员运算符(ostream 的成员;一个参数,作为操作数的类型,比如 int)函数 <<,我希望是这样的:std::cout.operator<< i;
---这不是很可笑吗?
那么,这两者到底是什么关系呢?
扩展问题:如果我想重载插入运算符以便 std::cout << my_obj;
工作(假设 my_obj 是用户定义类型 MyType 的实例),我应该这样做吗
a) ostream& operator<< (ostream& os, MyType obj);
在 MyType
或
b) 在 MyType 中:
class MyType
{
...
ostream& operator<< (MyType);
};
选项 b) 是否有效?它甚至有意义吗(我记得在某个地方看到过它......)?选项a)和b)有什么关系?
编辑 3 月 27 日
根据 ecatmur 的请求,这里有两个具有相同签名但位于不同名称空间中的重载。使用 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;
}
您想到的非成员重载是 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<<
。
对于您自己的类型,您正在考虑(非成员)friend operator<<
,这对于模板 类(Barton-Nackman trick)或那些operator<<
访问无法通过访问器获得的数据:
class MyType
{
...
friend std::ostream& operator<< (std::ostream&, MyType obj) { ... }
};
你提议的签名将允许你写 my_obj << my_obj
,这不太可能有多大意义。