简体   繁体   English

重载后 std::endl 的“operator<<”不匹配

[英]no match for ‘operator<<’ for std::endl after overload

I am sorry that I duplicate this question , but I don't have the reputation required to comment there and the answers there are not convincing for me.很抱歉我重复了这个问题,但我没有在那里发表评论所需的声誉,而且那里的答案对我来说没有说服力。

#include<iostream>

class my_ostream : public std::ostream
{
    public:
    std::string prefix;

    my_ostream():prefix("*"){}

    my_ostream& operator<<(const std::string &s){
        std::cout << this->prefix << s;
        return *this;
    }
};

int main(){
  my_ostream s;
  std::string str("text");
  s << str << std::endl;
}

Here I get:在这里我得到:

no match for 'operator<<' in 's.my_ostream::operator<<(((const std::string&)((const std::string*)(& str)))) << std::endl' 's.my_ostream::operator<<(((const std::string&)((const std::string*)(& str))))) << std::endl' 中没有匹配'operator<<'

and I don't understand why.我不明白为什么。 If it works for ostream, it should work for my_ostream.如果它适用于 ostream,它应该适用于 my_ostream。 This program works:该程序有效:

#include <iostream>
using namespace std;

class a{};
class b:public a{};
class c:public b{};

void f(a){cout << 'a' << endl;}
void f(b){cout << 'b' << endl;}
void f(b, a){cout << "b, a" << endl;}
void f(c){cout << 'c' << endl;}
void f(c, int){cout << "c, int" << endl;}

void f(a*){cout << "pa" << endl;}
void f(b*){cout << "pb" << endl;}
void f(b*, a*){cout << "pb, pa" << endl;}
void f(c*){cout << "pc" << endl;}
void f(c*, int){cout << "pc, int" << endl;}

int main(){
  a ao; b bo; c co;
  f(ao); f(bo); f(co);
  f(co, ao);
  a *pa=new(a); b *pb=new(b); c *pc=new(c);
  f(pa); f(pb); f(pc);
  f(pc, pa);
  return 0;}

It outputs:它输出:

a
b
c
b, a
pa
pb
pc
pb, pa

So simple overloading does not explain this error.如此简单的重载并不能解释这个错误。 Also, I do not introduce templates here, so undetermined template type parameters should not play a role.另外,我这里不介绍模板,所以未确定的模板类型参数应该不会起作用。 Reading the iostream code proves to be very difficult, so I appreciate any insight.阅读 iostream 代码证明是非常困难的,所以我很感激任何见解。

Simple overloading does explain this error.简单的重载确实解释了这个错误。 In fact, std::cout just complicates the issue.事实上, std::cout只是让问题复杂化了。 The following also doesn't work:以下也不起作用:

int main(){
  my_ostream s;
  s << 1;
}

The issue is that your operator << overload in effect hides all the overloads that are defined for the base class.问题是您的operator <<重载实际上隐藏了为基类定义的所有重载。

Roughly speaking, C++ does overload resolution after scope resolution.粗略地说,C++ 在作用域解析之后进行重载解析。 So C++ first checks if there's an operator << defined in the scope of your class.因此,C++ 首先检查在您的类的范围内是否定义了operator << There is!有! So it stops searching for more general functions right there and only considers the functions already found for overload resolution.因此它停止在那里搜索更通用的函数,只考虑已经找到的用于重载解析的函数。 Alas, there's only a single overload, for std::string so the call fails.唉,对于std::string只有一个重载,所以调用失败。

This can be fixed simply by defining operator << not as a member function but a free function:这可以通过将operator <<定义为一个自由函数而不是一个成员函数来简单地解决:

my_ostream& operator<<(my_ostream& out, const std::string &s) {
    std::cout << out.prefix << s;
    return out;
}

… but of course this only fixes some of your problems because your class definition is simply semantically wrong; ……但当然这只能解决您的一些问题,因为您的类定义在语义上是错误的; you cannot subclass the IO streams like this.你不能像这样子类化 IO 流。 Here my knowledge fails but I think in order to do what you want you should override the stream buffer's uflow function.在这里,我的知识失败了,但我认为为了做你想做的事,你应该覆盖流缓冲区的uflow函数。

Another way to fix this is declared as friend the operator<< overloading.解决此问题的另一种方法是将运算符<< 重载声明为友元。

class my_ostream : public std::ostream
{
   public:
     std::string prefix;

   my_ostream():prefix("*"){}

   template <class T>
     friend my_ostream& operator<<(my_ostream& my_os, const T& s){
        std::cout << my_os.prefix << s;
     return my_os;
   }
};

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM