Dlaczego konwersja standardowa nie działa?

0

Cześć, jestem w trakcie nauki C++ z Symfonii i natrafiłem na przykład, w którym nie mogę zrozumieć dlaczego była konieczność zastosowania operatora reinterpret_cast.

Oto przykład:

#include <iostream>
using namespace std;
//////////////////////////////////////////////////////////////
class wekt
{
	double x,y,z;
	
	friend ostream& operator<< (ostream& strumien_wyj, wekt& w)
	{
		strumien_wyj << w.x << " " << w.y << " " << w.z;
		return strumien_wyj;
	}
	
	friend istream& operator>> (istream& strumien_wej, wekt& w)
	{
		strumien_wej >> w.x >> w.y >> w.z;
		return strumien_wej;
	}
};
//////////////////////////////////////////////////////////////
class wektor_poch: public wekt
{
public:
	char opis[30];
	
	friend ostream& operator<< (ostream& strumien_wyj, wektor_poch& w)
	{
		strumien_wyj << reinterpret_cast<wekt&> (w);
		//strumien_wyj << w;							DLACZEGO NIE????
		
		strumien_wyj << " " << w.opis;
		return strumien_wyj;
	}
	
	friend istream& operator>> (istream& strumien_wej, wektor_poch& w)
	{
		strumien_wej >> reinterpret_cast<wekt&>(w);
		//strumien_wej >> w;							DLACZEGO NIE????
		
		strumien_wej >> w.opis;
		return strumien_wej;
	}
};
//////////////////////////////////////////////////////////////

int main()
{
	wektor_poch wekt1;	
	cin >> wekt1;	
	cout << "\n" << wekt1;
}

Dlaczego referencja do obiektu typu wektor_poch nie może być zamieniona na referencję do typu wekt?
Dlaczego to nie jest przypadek, w którym mogę skorzystać z konwersji standardowej z obiektu klasy pochodnej na obiekt klasy podstawowej?

Program się kompiluje ale nie daje się uruchomić ale to pewnie nie będzie zaskoczeniem dla kogoś kto będzie wiedział o co tu chodzi :)

2

Heh, piękny przykład dlaczego nie należy uczyć się z symfonii. reinterpret_cast jest tu absolutnie złym rozwiązaniem, a poprawnym jest static_cast.

Odnośnie samego pytania, dlaczego cast w górę jest konieczny - jak najbardziej masz rację, można niejawnie konwertować referencję klasy pochodnej na klasę bazową, ale zauważ, że masz dwa przeładowania operatora <<, które pasują do wektor_poch:

friend ostream& operator<< (ostream& strumien_wyj, wekt& w)
friend ostream& operator<< (ostream& strumien_wyj, wektor_poch& w)

Przekazując obiekt typu wektor_poch, drugi overload jest jednoznacznie lepszy i bez tego rzutowania będziesz miał nieskończoną rekursję, co nazywasz "niedaniem się uruchomić".

0

Fakt, dzięki za odpowiedź.

Od razu nasuwa się pytanie: dlaczego reinterpret_cast jest absolutnie złym rozwiązaniem?

1

@playmaker214 Dodając do odpowiedzi kq:
wystarczyłoby nie mieć zaprzyjaźnień tych zaprzyjaźnionych funkcji definiowanych w klasie pochodnej i by działało tak jak chcesz ;)

A reinterpret_cast po prostu rzuca "cokolwiek na cokolwiek" na Twoją własną odpowiedzialność. Przy rzutowaniach z klasy pochodnej na bazową wystarcza static_cast, bo jest prosta zależność między nimi.

Generalnie po to są te różne rzutowania, żeby ich właściwie używać.

1

@playmaker214
Generalnie tak - różnica między static_cast, a dynamic_cast jest taka, że dynamic dokonuje sprawdzenia w czasie działania programu (runtime check). Jeśli rzutujesz niewłaściwie, to zamiast wskaźnika dostaniesz nulla.

Static_cast stosujesz jeśli w danym miejscu wiesz "co rzutujesz na co". Przy polimorfizmie, i bardziej skomplikowanych callbackach (np. sprawdzenie od jakiego obiektu przyszedł) lepiej stosować dynamic_cast (zresztą ono idzie w parze ze wskaźnikami).

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