Operator[] i klasa abstrakcyjna

0

Znowu ja, znowu z problemem.
W moim programie obiekt klasy 'kino' ma wektor 'repertuar' wypełniony wskaźnikami na obiekty typu 'seans'. Seans to klasa abstrakcyjna której pochodnymi są 'film' i 'zwiastun' Dla obiektu kino przeciążyłem operator[] tak, aby przeszukiwał wektor 'repertuar' w poszukiwaniu podanego tytułu i zwrócił obiekt o tym tytule.

seans kino::operator[](string t)
{
	cout << "Operator [] klasy film" << endl;
	cout << "Sprawdza czy kino posiada film o podanym tytule" << endl;
	vector<seans*>::iterator iter1;
	vector<seans*>::iterator iter2;    
	iter1 = repertuar.begin();
	iter2 = repertuar.end();
	for (;iter1 != iter2; iter1++)
	{
		if((*iter1)->info()==t)
		{
			cout << "Film o podanym tytule znajduje sie w repertuarze kina" << endl;
			return (*iter1);
		}
	}
	cout << "Nie znaleziono" << endl;
}

Niestety takie rozwiązanie nie działa gdyż seans to klasa abstrakcyjna, natomiast gdy próbuję jako typ zwracany dać film lub zwiastun, kompilator wywala błąd, że zwracam typ seans a nie typ podany. Gdzie tu logika?

0

Rzutowanie.

0

Myślałem o tym ale nie za bardzo widzę sposób na rozwiązanie tego rzutowaniem. Chyba że istnieje sposób na wpisanie do jednej funkcji różnych typów zwracanych.

0

Rzutowanie bazowa -> pochodna jest o tyle niebezpieczne, że nie wiadomo na obiekt jakiej klasy wskazuje wskaźnik z iteratora, no chyba że jakoś jesteś w stanie te klasy rozróżnić z poziomu klasy bazowej. Druga sprawa to to, że nie przewidziałeś opcji gdzie operator nic nie znajduje. Co on wtedy zwróci?

0

Wcześniej w usuniętym poście dałeś rozwiązanie, które pomogło, ale teraz jest ono usunięte, było złe?
W razie nieznalezienia

 	*iter1 = NULL;
	return *(*iter1);

powinno wystarczyć.

0

Nie, nie było, tylko nie przeczytałem dalszej części Twojego posta, w kontekście której mój post wydał mi się niewiele wnoszący, więc go usunąłem ;)

W razie nieznalezienia

*iter1 = NULL;
return *(*iter1);

powinno wystarczyć.

2x błąd. Przypisując NULLa gubisz obiekt, na który wskazuje iter1. Następnie dokonujesz deferencji wskaźnika NULL - katastrofa gotowa. W przypadku, gdy zwracasz referencję jedynym wyjściem jest rzucenie jakiegoś wyjątku, co według mnie jest średnim rozwiązaniem, no ale co kto lubi...

0

Kolejny problem, ale pisze tutaj zeby nie spamować kolejnym tematem. Mam

vector <Type> kina;

Gdzie jako Type ustawiam 'kino' po którym dziedziczą klasy 'kino domowe' i 'kino objazdowe'. Operator [] wygląda tak:

kino siec<Type>::operator[](string t)
{
	vector<kino>::iterator iter1;
	vector<kino>::iterator iter2;    
	iter1 = kina.begin();
	iter2 = kina.end();
	for (;iter1 != iter2; iter1++)
	{
		if((*iter1).imie()==t)
		{
			return (*iter1);
		}
	}
	cout << "Nie znaleziono" << endl;
}

Dynamic cast robiony tradycyjnie:

		if (kino_objazdowe * kino = dynamic_cast<kino_objazdowe*>((*this)[wyb]))
			{
				menuko((*this)[wyb]);
			}

Zrzuca błędy error, cannot dynamic cast. Próbowałem chyba już każdej kombinacji wskaźników i referencji przy rzutowaniu i dalej nic.

0

A co Ty rzutujesz? Obiekt klasy kino na wskaźnik?! Nawet jakbyś rzutował wskaźniki, to z tego co podałeś vector zawiera obiekty klasy kino, zatem nie możesz rzutować wskaźników do tych obiektów na wskaźniki klas pochodnych, ponieważ nie masz tu do czynienia z polimorfizmem - kino nie jest kinem_objazdowym.

Tak na przyszłość, jeśli podajesz ponownie ten sam operator, to chociaż popraw błędy, o których była już mowa.

0

Operator do wektora kino akurat działa póki co dobrze, więc nie ruszałem, dodałem cerr na wypadek nie znalezienia. Więc w sytuacji gdy nie ma polimorfizmu jak sprawdzać klasę obiektu?

0

jak sprawdzać klasę obiektu?

A po co sprawdzać, jeśli nie ma polimorfizmu?

dodałem cerr na wypadek nie znalezienia

A co to zmieni? Skąd kod, który wywołuje operator [] będzie wiedział, że wartość zwrócona jest wartością... hmm, no właśnie jaką wartością, przecież operator nic nie zwraca w tym przypadku? :>

--- dodane ---

kino siec<Type>::operator[](string t)
{
        vector<kino>::iterator iter1;
        vector<kino>::iterator iter2;    

A nie tak przypadkiem?

kino siec<Type>::operator[](string t)
{
        vector<Type>::iterator iter1;
        vector<Type>::iterator iter2;    
0
0x666 napisał(a)

jak sprawdzać klasę obiektu?

A po co sprawdzać, jeśli nie ma polimorfizmu?

Ale chyba wektor przetrzyma i objazdowe i domowe, jak po zwykłym dziedziczą o ile pamiętam. A sprawdzanie mi potrzebne, bo każda z klas ma inne menu. Mechanizm zaplanowałem tak, wklepuję nazwe kina, program wyszukuje kino o takiej nazwie, sprawdza rodzaj kina i wyświetla odpowiednie menu.

0

Ale chyba wektor przetrzyma i objazdowe i domowe

Nie, przecież piszę o tym. Jak sam napisałeś, masz:

vector <Type> kina;

a Type to klasa kino, a ta nie jest kinem objazdowym/domowym. Co innego jakbyś w wektorze trzymał wskaźniki na kino, wtedy spokojnie mógłbyś przypisać tam wskaźnik na kino objazdowe/domowe. W operatorze z pierwszego postu masz tak właśnie zrobione.

0

Zmieniłem na

vector <Type*> kina

Ale dynamic casty tam gdzie pisałem nadal mi nie działają. Gdy piszę normalnie dostaję błąd o castowaniu class kino na class kino_objazdowe*. a gdy (*this)[wyb] zmieniam na *(*this)[wyb]. Błąd o braku operatora *.</cpp>

0

Przecież operator zwraca obiekt klasy kino! :-/ Pisałem już o tym, że nie możesz rzutować obiektu na wskaźnik. Wcześniej podałem Ci rozwiązanie, pomyśl trochę...

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