Модераторы: Daevaorn

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Перегрузка оператора вывода <<, с использованием абстрактного класса 
:(
    Опции темы
gabin
Дата 14.10.2011, 23:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


студент



Профиль
Группа: Участник
Сообщений: 28
Регистрация: 21.8.2008
Где: Харьков

Репутация: нет
Всего: нет



Здравствуйте. Хочу сделать перегрузку оператора вывода <<. 
Иерархия классов: (абстрактный)Component -> Engine -> GasEngine.
Если я объявляю статический объект класса GasEngine, то вывод работает без проблем:
Код

GasEngine mazdaEngine(2092.22,"Инжектор",553);
cout<<mazdaEngine;
Результат:
Код

Тип двигателя : Инжектор
Стоимость двигателя : 2092.22
Вес двигателя : 553

Но если я объявляю объект как указатель на абстрактный класс Component , то тут начинаются проблемы.
Код

Component* bmwEngine = new GasEngine(30133.1,"Инжектор",667);
cout<<bmwEngine;

Результат:
Код

0x9cd0008

Как сделать корректной перегрузку оператора вывода в данном случае?

Исходный код проекта, сделанного в Eclipse, прикрепляю.

Это сообщение отредактировал(а) gabin - 14.10.2011, 23:49

Присоединённый файл ( Кол-во скачиваний: 2 )
Присоединённый файл  Car.tar.gz 415,40 Kb
PM MAIL WWW ICQ Skype   Вверх
sQu1rr
Дата 14.10.2011, 23:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 597
Регистрация: 11.11.2008
Где: london

Репутация: 3
Всего: 13



Если оператор << перегружен для класса Component, то
Код

cout << *bmwEngine;


Добавлено через 1 минуту и 43 секунды
Соответственно, если нет, то что-то типо
Код

cout << dynamic_cast<GasEngine>(bmwEngine);

PM MAIL Skype GTalk   Вверх
gabin
Дата 15.10.2011, 00:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


студент



Профиль
Группа: Участник
Сообщений: 28
Регистрация: 21.8.2008
Где: Харьков

Репутация: нет
Всего: нет



Цитата(sQu1rr @ 14.10.2011,  23:57)
Если оператор << перегружен для класса Component, то
Код

cout << *bmwEngine;


Добавлено @ 23:59
Соответственно, если нет, то что-то типо
Код

cout << dynamic_cast<GasEngine>(bmwEngine);


Оператор << перегружен для класса Engine и GasEngine.
1-й вариант не проходит, падает при выполнении:
Код

В функции ‘int main()’:
../src/Lab.cpp:39:9: ошибка: no match for ‘operator<<’ in ‘std::cout << * bmwEngine’
/usr/include/c++/4.5/ostream:108:7: замечание: претенденты: std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(std::basic_ostream<_CharT, _Traits>::__ostream_type& (*)(std::basic_ostream<_CharT, _Traits>::__ostream_type&)) [with _CharT = char, _Traits = std::char_traits<char>, std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream<char>]
/usr/include/c++/4.5/ostream:117:7: замечание:              std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(std::basic_ostream<_CharT, _Traits>::__ios_type& (*)(std::basic_ostream<_CharT, _Traits>::__ios_type&)) [with _CharT = char, _Traits = std::char_traits<char>, std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream<char>, std::basic_ostream<_CharT, _Traits>::__ios_type = std::basic_ios<char>]
/usr/include/c++/4.5/ostream:127:7: замечание:              std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(std::ios_base& (*)(std::ios_base&)) [with _CharT = char, _Traits = std::char_traits<char>, std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream<char>]
/usr/include/c++/4.5/ostream:165:7: замечание:              std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(long int) [with _CharT = char, _Traits = std::char_traits<char>, std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream<char>]
/usr/include/c++/4.5/ostream:169:7: замечание:              std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(long unsigned int) [with _CharT = char, _Traits = std::char_traits<char>, std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream<char>]
/usr/include/c++/4.5/ostream:173:7: замечание:              std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(bool) [with _CharT = char, _Traits = std::char_traits<char>, std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream<char>]
/usr/include/c++/4.5/bits/ostream.tcc:91:5: замечание:              std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(short int) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/include/c++/4.5/ostream:180:7: замечание:              std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(short unsigned int) [with _CharT = char, _Traits = std::char_traits<char>, std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream<char>]
/usr/include/c++/4.5/bits/ostream.tcc:105:5: замечание:              std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(int) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/include/c++/4.5/ostream:191:7: замечание:              std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(unsigned int) [with _CharT = char, _Traits = std::char_traits<char>, std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream<char>]
/usr/include/c++/4.5/ostream:200:7: замечание:              std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(long long int) [with _CharT = char, _Traits = std::char_traits<char>, std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream<char>]
/usr/include/c++/4.5/ostream:204:7: замечание:              std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(long long unsigned int) [with _CharT = char, _Traits = std::char_traits<char>, std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream<char>]
/usr/include/c++/4.5/ostream:209:7: замечание:              std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(double) [with _CharT = char, _Traits = std::char_traits<char>, std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream<char>]
/usr/include/c++/4.5/ostream:213:7: замечание:              std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(float) [with _CharT = char, _Traits = std::char_traits<char>, std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream<char>]
/usr/include/c++/4.5/ostream:221:7: замечание:              std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(long double) [with _CharT = char, _Traits = std::char_traits<char>, std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream<char>]
/usr/include/c++/4.5/ostream:225:7: замечание:              std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(const void*) [with _CharT = char, _Traits = std::char_traits<char>, std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream<char>]
/usr/include/c++/4.5/bits/ostream.tcc:119:5: замечание:              std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(std::basic_ostream<_CharT, _Traits>::__streambuf_type*) [with _CharT = char, _Traits = std::char_traits<char>, std::basic_ostream<_CharT, _Traits>::__streambuf_type = std::basic_streambuf<char>]
make: *** [src/Lab.o] Ошибка 1


2-й вариант с dynamic_cast при компиляции ошибка: 
Код

cannot dynamic_cast ‘bmwEngine’ (of type ‘class Component*’) to type ‘class GasEngine’ (target is not pointer or reference)

А вариант 
Код

cout<<dynamic_cast<GasEngine*>(bmwEngine);

Выводит что-то типа 0x9089008.

Это сообщение отредактировал(а) gabin - 15.10.2011, 00:27
PM MAIL WWW ICQ Skype   Вверх
volatile
Дата 15.10.2011, 00:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2107
Регистрация: 7.1.2011

Репутация: 37
Всего: 85



Цитата(sQu1rr @  14.10.2011,  23:57 Найти цитируемый пост)
cout << dynamic_cast<GasEngine>(bmwEngine);

Не так работать вообще не будет. Вы здесь указатель пытаетесь привести к самому объекту, это абсурд.

Цитата(sQu1rr @  14.10.2011,  23:57 Найти цитируемый пост)
cout << *bmwEngine;

А так не будет виртуализации.
Чтобы заработала виртуализация, надо оператор вывода объявлять не для объекта, а для ссылки на объект.
Тогда будет все нормально


PM MAIL   Вверх
mes
Дата 15.10.2011, 00:38 (ссылка) |    (голосов:2) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



http://liveworkspace.org/code/1484f5e5f033...07f6756f5231fcb

Добавлено через 44 секунды
Код

#include <iostream>

struct IBase
{
   virtual void cout (std::ostream& o) const =0;
};

struct A : IBase 
{
   void cout (std::ostream& o) const
   {
       o << "classA ";
   }
};

struct B : IBase 
{
   void cout (std::ostream& o) const
   {
       o << "classB ";
   }
};

struct C : IBase 
{
   void cout (std::ostream& o) const
   {
       o << "classC ";
   }
};

std::ostream& operator << (std::ostream& o, const IBase& base)
{
   base.cout(o);
   return o;
}


int main ()
{
  IBase * a = new A ;
  IBase * b = new B;
  IBase * c = new C;
  
  std::cout << *c << *a << *b;
  
}



--------------------
PM MAIL WWW   Вверх
sQu1rr
Дата 15.10.2011, 11:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 597
Регистрация: 11.11.2008
Где: london

Репутация: 3
Всего: 13



Цитата(volatile @  15.10.2011,  00:38 Найти цитируемый пост)
Не так работать вообще не будет. Вы здесь указатель пытаетесь привести к самому объекту, это абсурд.

Я и не говорил что будет, я сказал что-то типо этого. Понятно, что указатель нужно привести к указателю smile
PM MAIL Skype GTalk   Вверх
gabin
Дата 15.10.2011, 22:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


студент



Профиль
Группа: Участник
Сообщений: 28
Регистрация: 21.8.2008
Где: Харьков

Репутация: нет
Всего: нет





http://liveworkspace.org/code/b7a74e931da8...7089a4519e27ff3
Сделал по аналогии с вашим примером но теперь в методе класса не работает cout: 
 
Код

source.cpp: In member function 'virtual void Engine::printData()':
source.cpp:65:10: error: invalid use of member (did you forget the '&' ?)
source.cpp:66:10: error: invalid use of member (did you forget the '&' ?)

Build finished with errors

PM MAIL WWW ICQ Skype   Вверх
volatile
Дата 15.10.2011, 23:27 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2107
Регистрация: 7.1.2011

Репутация: 37
Всего: 85



Цитата(gabin @  15.10.2011,  22:47 Найти цитируемый пост)
теперь в методе класса не работает cout:

уберите лишнее, и все заработает
http://liveworkspace.org/code/6b056ba78f64...db34c799df835e3

PM MAIL   Вверх
volatile
Дата 15.10.2011, 23:45 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2107
Регистрация: 7.1.2011

Репутация: 37
Всего: 85



Или, если вам нужна именно printData(), то так http://liveworkspace.org/code/6c8dfbc7604a...3d344af77d82951

А вообще идея называть методы именем cout - не очень хорошая идея.

PM MAIL   Вверх
gabin
Дата 15.10.2011, 23:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


студент



Профиль
Группа: Участник
Сообщений: 28
Регистрация: 21.8.2008
Где: Харьков

Репутация: нет
Всего: нет



Цитата(volatile @ 15.10.2011,  23:27)
Цитата(gabin @  15.10.2011,  22:47 Найти цитируемый пост)
теперь в методе класса не работает cout:

уберите лишнее, и все заработает
http://liveworkspace.org/code/6b056ba78f64...db34c799df835e3

Спасибо. 


PM MAIL WWW ICQ Skype   Вверх
mes
Дата 16.10.2011, 10:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(volatile @  15.10.2011,  22:45 Найти цитируемый пост)
А вообще идея называть методы именем cout - не очень хорошая идея.

особенно для тех кто любит :
Цитата

using namespace std;



--------------------
PM MAIL WWW   Вверх
gabin
Дата 16.10.2011, 19:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


студент



Профиль
Группа: Участник
Сообщений: 28
Регистрация: 21.8.2008
Где: Харьков

Репутация: нет
Всего: нет



В ходе дальнейшего расширения кода возникла проблема: реализовал шаблонный класс, который выполняет функции контейнера.
При добавлении в него POD объектов, контейнер работает без проблем - выводит через оператор << всё содержимое.
Но при добавлении полиморфных объектов базового абстрактного класса он опять выводит адреса. 
Странно, ведь в main() они успешно выводятся(да и оператор << перегружен), а вот в контейнере не хотят...
Вот код - http://liveworkspace.org/code/a4b8d24245e0...24d0091fa4b323f
Подскажите пожалуйста как разрешить эту проблему
PM MAIL WWW ICQ Skype   Вверх
mes
Дата 16.10.2011, 20:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(gabin @  16.10.2011,  18:54 Найти цитируемый пост)
Подскажите пожалуйста как разрешить эту проблему 

разыменовывайте указатель.. 



--------------------
PM MAIL WWW   Вверх
gabin
Дата 16.10.2011, 20:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


студент



Профиль
Группа: Участник
Сообщений: 28
Регистрация: 21.8.2008
Где: Харьков

Репутация: нет
Всего: нет



Цитата(mes @ 16.10.2011,  20:00)
Цитата(gabin @  16.10.2011,  18:54 Найти цитируемый пост)
Подскажите пожалуйста как разрешить эту проблему 

разыменовывайте указатель..

Успешно, но теперь не работает с POD объектами.
Получается, что шаблонный класс не универсален? И нужно реализовывать 2 шаблонных класса - для статических и для динамических объектов?
PM MAIL WWW ICQ Skype   Вверх
mes
Дата 16.10.2011, 22:00 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(gabin @  16.10.2011,  19:56 Найти цитируемый пост)
Получается, что шаблонный класс не универсален? 

Вы просто не умеете их готовить © smile

чтоб заработал, можно например так (на скорую руку):
http://liveworkspace.org/code/1d3aa15e9983...ce8579b462fa603




Это сообщение отредактировал(а) mes - 16.10.2011, 22:01


--------------------
PM MAIL WWW   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0976 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.