Dziedziczenie przeładowanego operatora <<

0

Witam,

Mam problem z dziedziczeniem operatora "<<". W programie chciałbym zrobić coś takiego:

cout << T << endl;

Gdzie T to obiekty klas Samochód, Motor, Dom - wszystkie dziedziczą po klasie podstawowej Produkt. Parametrem formalnym funkcji jest referencja do obiektu klasy Produkt, ale jak wiadomo kompilator sam sobie dokonuje konwersji, gdy przekażę mu obiekt klasy pochodnej. Jak to jednak wygląda przy korzystaniu z operatora "<<"? Stworzyłem oddzielne operatory "<<" dla klas pochodnych, jednak pojawiają się błędy i program nie chce się skompilować (unresolved external error).

0

Wklej więcej kodu.

operator<< jest specyficzny, przy wywoływaniu
cout << T;
operator<< jest wywoływany na obiekcie cout (którego nie możesz przeciążyć)... a raczej nie jest, bo jest to zrealizowane przez funkcje globalne.

Trochę więcej tu:
http://pl.wikibooks.org/wiki/C++/Przeciążanie_operatorów#Przyk.C5.82ad_zastosowania

Jednak nie jest to istotne przy typie błędu jaki zwraca kompilator, więc - jak wyżej - wlej więcej kodu.

0

Taki operator nie może być metodą klasy bo kolejność argumentów musiałaby być odwrotna! To musi być zaprzyjaźniona z klasą funkcja. Czemu?
Wywołanie cout << T; to jest to samo co
operator<<(cout,T)
czyli
cout.operator<<(T)
Gdyby to była metoda klasy T to mógłbyś mieć co najwyżej
T << cout
Co cię raczej nie interesuje.
Idąc dalej: skoro to funkcja zaprzyjaźniona a nie metoda klasy to niestety polimorfizm ci tu nie pomoże.

0

Zupełnie nie pomyślałem. Zadeklarowałem je oczywiście jako funkcje zaprzyjaźnione, a chciałem coś dziedziczyć :) Wybaczcie moją głupotę! Nasuwa się więc pytanie: jak uniwersalnie rozwiązać ten problem? Zrobić jakiegoś switcha i manualnie uruchamiać operatory "<<" w zależności od klasy, z której obiektem mamy do czynienia?

1

Nie rób żadnych switch'y, żeby sprawdzać typ obiektu. Nigdy.

Zamiast tego, stwórz jedną funkcję globalną
ostream& operator<<(ostream& wyjscie, const& Produkt) { return Produkt.WypiszNaToWyjscie(wyjscie); };

Funkcję Produkt::NaWyjscie zadeklaruj jako czysto wirtualną ( virtual ostream& WypiszNaToWyjscie(ostream&) const = 0; ).
Overridujesz ( jaki jest polski odpowiednik tego terminu?! ) ją w każdej klasie dziedziczącej z Produkt.

1

@Bent tak jak napisał kolega @4ggr35510n zrób sobie w tej hierarchii klas wirtualną metodę w stylu javowego toString() i wewnątrz operatora<< z niej korzystaj :)

0

Albo jeszcze jedna opcja, z innego podejścia:
Zaimplementuj w klasie Produkt ( i pochodnych ) operator char*.
cout << T, spróbuje przekonwertować T na char* i dzięki temu operator char* zostanie wywołane.

Oczywiście poprzednie rozwiązanie jest lepsze. ( gdyby ktoś kiedyś w przyszłości dziedziczył z klasy Produkt i implementował operator int(), zachowanie cout<<T byłoby niejednoznaczne ( potrzebna byłaby konwersja jawna ) ).

0

Muszę przyznać, że to, o czym napisaliście jest dla mnie zupełnie nowe. Spróbowałem napisać coś i wyszło mi coś takiego:

Globalna funkcja operator<<:

ostream& operator<<(ostream& os, const Product& p) {

	return p.show(os);

}; 

Klasa Product:

virtual ostream& show(ostream& os) const = 0;
friend ostream& operator<<(ostream &os, const Product& p);

Przykładowa klasa dziedzicząca (Car):

virtual ostream& show(ostream& os) const {
			os << this->brand << " " << this->model << endl;
			return os;
		};

Efekt jest taki, że użycie:

ostream& operator<<(ostream &o, Policy& p) {

	o << "Product: " << p.getProduct().show(o) << endl << endl;

	return o;

};

Powoduje wypisanie na ekranie rzeczywiście marki i modelu, ale PÓŹNIEJ napisu: "Product: tu chyba adres w pamięci". Co robię źle?

0

A jak zrobisz tak zeby show() zwracało zwyłego stringa?

1
o << "Product: " << p.getProduct().show(o) << endl << endl;

show(o) zwraca ostream& - to ten twój adres w pamięci (oprócz wypisania tego adresu, skutkiem ubocznym jest wypisanie obiektu poprzez samo wywołanie).
Po to przeciążasz operator<<, żeby z niego korzystać - nie wywołuj jawnie funkcji show:

o << "Product: " << p.getProduct() << endl << endl;
0

Rzeczywiście, w ogóle nie korzystałem z operatora <<. Już oczywiście działa :) Dzięki!

1 użytkowników online, w tym zalogowanych: 0, gości: 1