1

很抱歉我重复了这个问题,但我没有在那里发表评论所需的声誉,而且那里的答案对我来说没有说服力。

#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;
}

我在这里得到:

's.my_ostream::operator<<(((const std::string&)((const std::string*)(& str))) 中的 'operator<<' 不匹配) << std::endl' </p>

我不明白为什么。如果它适用于 ostream,它应该适用于 my_ostream。该程序有效:

#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;}

它输出:

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

如此简单的重载并不能解释这个错误。另外,我这里不介绍模板,所以未确定的模板类型参数应该不会起作用。阅读 iostream 代码被证明是非常困难的,所以我很感激任何见解。

4

2 回答 2

4

简单的重载确实解释了这个错误。事实上,std::cout只是使问题复杂化。以下也不起作用:

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

问题是您的operator <<重载实际上隐藏了为基类定义的所有重载。

粗略地说,C++ 在范围解析之后会重载解析。所以 C++ 首先检查你的类的范围内是否有operator <<定义。有!所以它停止在那里搜索更通用的函数,只考虑已经找到的函数来解决重载问题。唉,只有一个重载,std::string所以调用失败了。

这可以通过不定义operator <<为成员函数而是定义为自由函数来简单地解决:

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

…但是当然这只能解决你的一些问题,因为你的类定义在语义上是错误的;你不能像这样子类化 IO 流。在这里我的知识失败了,但我认为为了做你想做的事,你应该覆盖流缓冲区的uflow功能。

于 2012-11-30T09:37:09.707 回答
1

解决此问题的另一种方法是将 operator<< 重载声明为友元。

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;
   }
};
于 2019-02-21T02:33:40.973 回答