自从我从 C 转移到 C++ 后,我对 STL 的格式化输出有疑问。ostreams 如何区分一种基本类型和另一种?
在具有 printf 和格式化字符串的 C 中,它非常简单,但在 C++ ostreams 中以某种方式自动区分基本类型。这让我很困惑。
例如,在下面的代码中,
int i;
float f;
std::cout << i << std::endl;
std::cout << f << std::endl;
cout 如何“知道” i是 int 而f是 float?
编译器将运算符转换为函数调用。以便
std::cout << i
变成
operator<<(std::cout, i)
在标准库头文件深处的某个地方,有函数声明(功能上等同于):
std::ostream& operator<<(std::ostream& o, int i);
std::ostream& operator<<(std::ostream& o, double d);
也operator<<就是超载了。进行函数调用时,编译器会选择与传入参数最匹配的函数重载。
在 的情况下std::cout << i,int选择重载。在 的情况下std::cout<<d,double选择重载。
您可以通过一个人为的示例相当简单地看到函数重载的作用:
#include <stdio.h>
void print(int i) {printf("%d\n", i);}
void print(double d) {printf("%f\n", d);}
int main()
{
int j=5;
double f=7.7;
print(j);
print(f);
}
产生输出:
5
7.700000
自己试试吧:http: //ideone.com/grlZl。
编辑:正如 Jesse Good 所指出的,有问题的函数是成员函数。所以我们真的有:
std::cout << i
变成
std::cout.operator<<(i)
并且在标题中有声明(相当于):
class ostream {
ostream& operator<<(int i);
ostream& operator<<(double d);
...
};
然而,同样的基本思想也成立。
每种类型(int、float 等)都有 operator<< 重载。然后编译器将在编译时选择正确的那个。通常,运算符<< 具有形式std::ostream& operator<<(std::ostream& stream, int number ),其中函数是定义在 std 命名空间中的全局函数。您可以通过在您自己的命名空间中声明此函数来覆盖该函数的定义(这是通过 Argument Dependent Lookup 完成的)。
该函数返回对流的引用这一事实意味着您可以将它们串在一起。请记住,每当您看到 operator<<,它实际上只是一个函数调用。
如果你想看看,并且你正在使用 VS,打开
C:\Program 文件 (x86)\Microsoft Visual Studio 9.0\VC\include\ostream。
如果你好奇的话,你会在那里找到所有的定义。
第二个参数的重载决议operator<<
函数重载是编译时多态的一种形式。一个简单的例子:
void times_two(int& x) { x *= 2; }
void times_two(double& x) { x *= 2; }
int i = 2;
double d = 2.5;
times_two(i); // i now 4
times_two(d); // d now 5.0
在std::ostreams such的情况下std::cout,operator<<()函数以类似的方式重载。从 GCC 3.4.4 附带的标准库中:
__ostream_type&
operator<<(int __n);
__ostream_type&
operator<<(double __f);
这是一个重载的 ostream 运算符 <<。在 c++ 中,您可以根据其参数重载函数名称。这基本上就是这里发生的事情。http://www.cplusplus.com/reference/iostream/ostream/operator%3C%3C/