2012-11-29 3 views
1

Прошу прощения за то, что я дублирую this question, но у меня нет репутации, необходимой для комментариев, и ответы там не убедительны для меня.нет соответствия для 'operator <<' для std :: endl после перегрузки

#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 :: оператор < < (((Const станд :: строка &) ((Const станд: : строка *) (& ул)))) < < станд :: епсИ»

, и я не понимаю, почему. Если он работает для 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 оказывается очень сложным, поэтому я ценю любое понимание.

+0

Оказывается, что 'std :: ostream s;' тоже не работает, поэтому это довольно сложно и трудно понять. –

+0

Интернет говорит, что 'cout' имеет тип' ostream'. Кто-нибудь может развязать этот узел? :) –

ответ

2

Простая перегрузка делает объясняет эту ошибку. Фактически, 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; 
} 

... но, конечно, это только исправляет некоторые из ваших проблем, потому что ваше определение класса просто семантически неправильно; вы не можете подклассифицировать потоки ввода-вывода следующим образом. Здесь мои знания терпят неудачу, но я думаю, что для того, чтобы делать то, что вы хотите, вы должны переопределить функцию uflow буфера потока.

+1

Спасибо за ваш ответ. Я не могу поверить, что C++ не перегружает унаследованные функции (это не так, я проверял), и я не могу поверить, что я этого не знал. Рад узнать, что ostream не подклассифицируется. После того, как я вынул 'operator <<' из my_ostream, программа компилируется, но она выдает' std :: bad_cast', когда она достигает 'std :: endl'. Пожалуйста, скажите мне, почему это происходит. uflow, по-видимому, определяется только для файлов 'filebuf :: uflow'. Может быть, я должен переопределить 'std :: streambuf :: sputc' и вызвать его из функции overriding? –

 Смежные вопросы

  • Нет связанных вопросов^_^