Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

C++: дружественные ф-ии вывода

17K
01 ноября 2006 года
Bosheit
26 / / 28.10.2006
Предположим, существует АБСТРАКТНЫЙ класс ClassA.
У него есть потомки ClassB1, ClassB2 и т.д., у каждого из которых есть своя дружественная функция вывода.
Код:

class ClassA
{
virtual void Func() = 0;
};

class ClassB1 : public ClassA
{
void Func() {};
friend ostream& operator<<(ostream& os, const ClassB1& b);
};

class ClassB2 : public ClassA
{
void Func() {};
friend ostream& operator<<(ostream& os, const ClassB2& b);
};

ostream& operator<<(ostream& os, const ClassB1& b) {/* */ return os; };
ostream& operator<<(ostream& os, const ClassB2& b) {/* */ return os; };

Как теперь сделать так, чтобы работал код типа:
ClassA* a[2];
a[0] = new ClassB1();
a[1] = new ClassB2();
for(int i=0; i<2; i++)
cout << *a;

Ведь понятно, что для ClassA ф-ии вывода нет (и быть не может).
Естественно, ошибка: "error C2679: binary '<<' : no operator found which takes a right-hand operand of type 'ClassA'"
Ясно, что для виртуальных функций-членов в подобной ситуации будут вызваны ф-ии потомков, но ведь не бывает же "виртуальных дружественных функций"? Как быть?
3
01 ноября 2006 года
Green
4.8K / / 20.01.2000
[QUOTE=Bosheit]
Ведь понятно, что для ClassA ф-ии вывода нет (и быть не может).
Естественно, ошибка: "error C2679: binary '<<' : no operator found which takes a right-hand operand of type 'ClassA'"
[/QUOTE]
Почему не может? Может.
Создай такую функцию и ошибки не будет.

[QUOTE=Bosheit]
Ясно, что для виртуальных функций-членов в подобной ситуации будут вызваны ф-ии потомков, но ведь не бывает же "виртуальных дружественных функций"? Как быть?[/QUOTE]
Так сделай виртуальный метод вывода
Код:
class ClassA
{
    virtual ostream& out(ostream& os) const = 0;
    friend ostream& operator<<(ostream& os, const ClassA& a) {
        return a.out(os);
    }
};

class ClassB1 : public ClassA
{
    ostream& out(ostream& os) const {
        os << "ClassB1::out(ostream& os)";
        return os;
    }
};

class ClassB2 : public ClassA
{
    ostream& out(ostream& os) const {
        os << "ClassB2::out(ostream& os)";
        return os;
    }
};
17K
01 ноября 2006 года
Bosheit
26 / / 28.10.2006
Воистину всё гениальное просто! Ну, как же я сам не додумался, просто поразительно! Спасибо, Green!
38K
01 мая 2008 года
sorrelcat
6 / / 17.04.2008
Здравствуйте!
У меня другая ситуация: есть класс str - строки, для которого определена дружественная функция вывода:
[HTML]
class str //класс строки
{
public://закрытая секция
int length; //длина строки
char *p; //указатель на массив символов для строки
public: //открытая секция класса
friend ostream &operator<<(ostream &, str &); //перегруженный дружественный оператор вывода в стандартный поток
};

ostream& operator<<(ostream& stream, str &t)
{
str temp=t;
for (int i=0; i<t.length; ++i) stream << temp.p;
return stream;
}
[/HTML]
Есть класс элементов двусвязного списка:
[HTML]
class delem //класс элемента двусвязного списка
{
public:
str data; //строка данных списка
delem *next; //указатель на следующий элемент
delem *prev; //указатель на предыдущий элемент
delem(); //конструктор по умолчанию
delem(const delem &); //конструктор копий
~delem(); //деструктор
delem operator=(delem); //перегруженный оператор присваивания, копирует данные и связи
};
[/HTML]
И есть класс двусвязного списка строк, для которого нужно также перегрузить оператор вывода в поток:
[HTML]
class dlist //собственно класс двусвязного списка
{
private: //закрытая секция
delem *head; //указатель на голову списка
delem *tail; //указатель на хвост списка
int count; //количество элементов списка
public: //открытая секция
friend ostream& operator<<(ostream&, dlist);

};

ostream& operator<<(ostream& stream, dlist &t)
{
delem temp=t.get_head();
do
{
stream<<temp.data<< endl; //:mad:
}
while (temp.next);
return stream;
}
[/HTML]
При компиляции выдает ошибку: error C2593: 'operator <<' is ambiguous (место ошибки в коде отмечено :mad:). Как перегрузить это корректно? Может, само построение перегрузок неправильное?
320
01 мая 2008 года
m_Valery
1.0K / / 08.01.2007
Для таких тем есть раздел Студентам;) http://forum.codenet.ru/showthread.php?t=44194 - тут класс строка и операторы все есть.
38K
01 мая 2008 года
sorrelcat
6 / / 17.04.2008
Цитата: m_Valery
Для таких тем есть раздел Студентам;) http://forum.codenet.ru/showthread.php?t=44194 - тут класс строка и операторы все есть.


Дело в том, что класс строки у меня работает, и перегрузка оператора вывода в поток для него выполняется корректно. Но когда я для другого класса перегружаю оператор вывода также дружественным:
[HTML]
class str //класс строки
{
public://закрытая секция
int length; //длина строки
char *p; //указатель на массив символов для строки
public: //открытая секция класса
friend ostream &operator<<(ostream &, str &); //перегруженный дружественный оператор вывода в стандартный поток
};
ostream& operator<<(ostream& stream, str &t)
{
str temp=t;
for (int i=0; i<t.length; ++i) stream << temp.p;
return stream;
}

class dlist //собственно класс двусвязного списка
{
private: //закрытая секция, delem - класс элемента списка
delem *head; //указатель на голову списка
delem *tail; //указатель на хвост списка
int count; //количество элементов списка
public: //открытая секция
void echo_dlist(); //вывод списка в стандартный поток
// friend ostream& operator<<(ostream&, dlist);

};

ostream& operator<<(ostream& stream, dlist &t)
{
delem temp=t.get_head();
do
{
stream<<temp.data<< endl;
}
while (temp.next);
return stream;
}
[/HTML]
Возникает описанная проблема (компилятор не может определить, какую функцию использовать). Для других перегруженных операторов таких ошибок не выдается. В чём ошибка?

Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог