重载左移位运算符

overloading left shift operator

本文关键字:运算符 左移 重载      更新时间:2023-10-16

我已经研究并发现,当您想要重载输出流操作符为cout时,那么正确的方法是这样做:

std::ostream& operator<<(std::ostream& os, const T& obj)

这个函数必须在类之外定义,因为这里的操作符<<实际上是ostream中定义的友元函数,你正在使用它。但是,问题是,这个函数到底是如何在ostream中定义的?因为这个函数有两个参数,第二个参数是用户自定义的,所以他们无法猜测这里会发生什么。

特定类的重载应该如下所示:

std::ostream& operator<<(std::ostream& os, const MyClass& obj)

编译器/库如何采用第二个参数的泛型定义,特别是因为在c++中没有泛型类(如Java中的Object)这样的东西?

我想你是搞混了:

operator<& lt;实际上是ostream中定义的友元函数,你正在使用它。

确实 operator <<class std::ostream中被定义。实际上,它内部定义了几个版本。但这些与我们无关。而且,它们不是friend函数:根据定义,friend函数定义在类之外。

但是这与你定义的函数无关,因为你的operator <<函数是一个独立的重载,当你将你的类型的对象作为第二个参数传递给<<调用时(第一个参数是std::ostream&),它被调用。

正如TemplateRex所解释的那样,查找适当函数的确切方法是通过依赖于参数的查找。但更基本的是,您只需要知道为给定参数类型AB定义二进制操作符有两种方式:

  • 作为A类内部的成员函数,并且只有一个参数,类型为B
  • 作为一个自由函数,有两个参数,类型为AB

当使用操作符时,这两个定义都是候选函数。(但是有几个操作符,比如拷贝赋值,只能在类内部定义,不能在类外部定义)。那么,回到你的问题:

这个函数是如何在ostream中定义的?因为这个函数有两个参数,第二个参数是用户自定义的,所以他们无法猜出里面是什么

答案是不是ostream中定义的。唯一的定义是你的,它在外面。

c++函数可以重载,即多个具有相同名称但采用不同参数的函数可以共存。编译器要经历三个步骤:名称查找、参数推导和重载解析。最后,只有一个函数重载可以作为最佳匹配而存在。这些概念的简单介绍可以从Stephan T. Lavavej Core c++系列的前三个视频中获得。

一个常见的情况是用户定义的类S在命名空间N中(可以是全局的),在同一个命名空间中有一个operator<<(ostream&, S const&)重载。

namespace N {
class S 
{
    // bla
};
std::ostream& operator<<(std::ostream& os, S& const& obj)
{
    // print in terms of public interface of S
    // (else, deckare this a friend function inside S)
    return os;
}
} // N
int main()
{
    std::cout << S(); // operator<<(ostream&, S const&) is the best match
}

名称查找很微妙,在本例中,它通过所谓的参数依赖查找工作,查找与函数参数关联的名称空间。对于上面的代码,这些命名空间是std(所有标准库函数所在的地方)和N(您的重载operator<<(ostream&, S const&)所在的地方)。参数推导将推导出正确的类型,重载解析将发现您的重载是最佳匹配(在本例中,很可能是唯一匹配)。

因此,能够使用"本机"语法打印用户定义的类型。

:在这种情况下,它不是"左移"操作符,而是"流插入"操作符,尽管后者与前者具有相同的词法形式。