• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

question-closed C++, dziedziczenie - zadanie z książki C++ Szkoła Programowania ( lekka niepewność )

+1 głos
89 wizyt
pytanie zadane 14 czerwca w C i C++ przez Jakub 0 Stary wyjadacz (10,230 p.)
zamknięte 14 czerwca przez Jakub 0

Witam, mam takie zadanie:

Podpunkty:
a) zrobiłem

b) też proste pytanie

c) Funkcja operator<<() z banalnych powodów nie może być wirtualna, nie jest metodą klasy...

Nie wiem jednak dlaczego właściwie metoda operator=() nie jest wirtualna, właściwie w każdym przypadku. Przecież kiedy mamy taką sytuacje:

Port& p = jakisObiektTypuVintagePort; 
VintagePort vp("cos",0,"cos",0); 
p = vp; 

To nie chcemy zmienić jedynie składowych klasy bazowej ( klasy jakiego typu jest referencja ), ale zależy nam na tym żeby użyć operatora przypisania klasy na którą referencja wskazuje, a w tym operatorze w klasie pochodnej wywołamy dopiero operator przypisania klasy bazowej.

Mógłbym sobie to wytłumaczyć że domyślnie operator przypisania wykona się dla typu obiektu na który wskazuje referencja/wskaźnik, jednak widziałem że da się mimo wszystko zrobić op= wirtualny :/ Nie rozumiem tego.

Będę wam bardzo wdzięczny za wytłumaczenie sytuacji :)

komentarz zamknięcia: już wiem
komentarz 14 czerwca przez Jakub 0 Stary wyjadacz (10,230 p.)
Jeżeli pytanie jest nie jasne  to będę wdzięczny za info, bo coś cisza :/
komentarz 14 czerwca przez RafalS Maniak (52,580 p.)
Cisza bo ludzie sa w pracy albo w szkole :p sam bym sie z checia zmierzyl z problemem ale dopiero po 17 :p
komentarz 14 czerwca przez Jakub 0 Stary wyjadacz (10,230 p.)
Też bym tak sądził i to jest zrozumiałe, ale na inne pytania są odpowiedzi. Oczywiście mi się nie śpieszy ani nie jestem natarczywy, po prostu chce się upewnić bo czasami mi się wydaje że pytanie jest logiczne a  w rzeczywistości nie zrozumiałe.
komentarz 14 czerwca przez monika90 Pasjonat (16,260 p.)
Albo klasa ma semantykę wartości i wtedy ma operator przypisania, albo jest częścią hierarchii klas z funkcjami wirtualnymi i wtedy go nie ma. Nie powinno się tych dwóch rzeczy łączyć, bo po co komplikować?
komentarz 14 czerwca przez Jakub 0 Stary wyjadacz (10,230 p.)
Wiem że to by nie miało sensu ( chodziło mi tylko że do czegoś pewnie służy możliwość robienia wirtualnych operatorów przypisania ) Mam jeszcze jedno pytanie, bo zauważyłem pewną rzecz i nie wiem czy tak powinno być czy to może jest mój błąd w programie. Mam obiekt klasy pochodnej ( VintagePort ) i wskaźnik na niego typu klasy bazowej ( Port ). Gdy za pomocą wskaźnika przypisuje nową wartość do obiektu VintagePort to wywołuje się operator przypisania klasy bazowej a nie pochodnej. Więc tylko składowe podobiektu z klasy Port będą miały nową wartość. Gdy nie używam do przypisania wskaźnika typu klasy bazowej to jest już ok.
komentarz 14 czerwca przez RafalS Maniak (52,580 p.)
Rozpisze Ci to dzis wieczorem jak bd mial dostep do klawiatury a nie ekranu tel :p
komentarz 14 czerwca przez RafalS Maniak (52,580 p.)
Edytowałem odpowiedz, bo do komentarzy nikt nie patrzy, a może komuś się to przyda.

1 odpowiedź

+1 głos
odpowiedź 14 czerwca przez RafalS Maniak (52,580 p.)
edycja 14 czerwca przez RafalS
 
Najlepsza

Virtual operetor = bylby tutaj bez sensu, bo sygnatury funkcji sa inne, przyjmuja one inne argumenty, czyli i tak mamy 2 rozne metody, wiec wywolanie polimorficzne i tak wybierze jedyna mozliwa opcje.

Zacznijmy od prostego przykładu:

#include <iostream>
#include <string>
using namespace std;

class A {
public:
	A(int a) : a(a){}
	int a;
	A& operator=(const A& arg) {
		a = arg.a;
		return *this;
	}
};

class B : public A {
public:
	B(int a, int b) : A(a), b(b) {}
	int b;
	B& operator=(const B& arg) {
		b = arg.b;
		return *this;
	}
};

int main() {
	B b(1,2);
	B b2(3, 4);
	b2 = b;
	cout << b2.a << " " << b2.b << endl;
	return 0;
}

Jak widzisz składowa a nie przekopiowała się, bo musielibyśmy wywołać jawnie operator= klasy bazowej:

A::operator=(arg);

Teraz już kopiowane jest wszystko. 

Tak można tutaj zrobić polimorfizm, ale polimorfizm nie zadziała na lewym argumencie operatora, więc trzeba zrobić brzydki cast, a tego robić nie lubimy:

#include <iostream>
#include <string>
using namespace std;

class A {
public:
	A(int a) : a(a){}
	int a;
	virtual A& operator=(const A& arg) {
		a = arg.a;
		return *this;
	}
};

class B : public A {
public:
	B(int a, int b) : A(a), b(b) {}
	int b;
	//dodanie tutaj override wywali blad, bo to wcale nie jest przesloniecie
	virtual B& operator=(const B& arg) { 
		A::operator=(arg);
		b = arg.b;
		return *this;
	}
	//tutaj mamy przesloniecie, sygnatura sie zgadza
	virtual A& operator=(const A& arg) override {
		cout << "juhu udalo sie" << endl;
		//zawsze wejdziemy tutaj niezaleznie czy arg jest obiektem A lub B
		//problem jest taki, ze nie wiadomo tutaj czy arg jest obiektem B czy A
		//zeby to określić trzeba by zrobić brzydkiego dynamic_casta
		a = arg.a;
		try {
			const B& argB = dynamic_cast<const B&>(arg);
			b = argB.b;
		}
		catch (std::bad_cast& e) {
			cout << "arg byl jednak typu A" << endl;
			b = 69; //default value
		}
		return *this;
	}
};

int main() {
	A a(10);
	B b(1,2);
	A& aref = a;
	A& bref = b;
	bref = b;

	bref = a;
	return 0;
}

 

komentarz 14 czerwca przez Jakub 0 Stary wyjadacz (10,230 p.)
edycja 14 czerwca przez Jakub 0
Ale gdyby sygnatury funkcji były takie same to trzeba by było dać ten operator jako wirtualny?
komentarz 14 czerwca przez Jakub 0 Stary wyjadacz (10,230 p.)

@RafalS

Ok, dzięki. O rzutowaniach static_cast, dynamic_cast... jeszcze zupełnie nic nie wiem, jeszcze nie miałem tego w książce. 

Napisałem też komentarz z pytaniem odnośnie operatora przypisania a wskaźnikiem/referencją typu klasy bazowej na klasę pochodną, również był bym bardo wdzięczny z wyjaśnienie tego. Jeżeli zaistniała sytuacja wynika z "działania c++" a nie mojego błędu to użycie wtedy wirtualnego operatora= nie miało by uzasadnionego sensu?

komentarz 14 czerwca przez RafalS Maniak (52,580 p.)
Wynika to z działania C++. Gdybyś chciał, żeby działało musiałbyś zrobić tak jak ja z virtualnym operatorem i łapaniem wyjątku w drugim przykładzie.
komentarz 14 czerwca przez Jakub 0 Stary wyjadacz (10,230 p.)
Dziękuje za wszystko, mam nadzieje że w książce będzie też coś potem na ten temat.

Podobne pytania

0 głosów
1 odpowiedź 56 wizyt
Porady nie od parady
Komentarze do pytań nie służą do odpowiadania, od tego jest wydzielona sekcja odpowiedzi. Funkcją komentarzy jest natomiast możliwość uzyskania dodatkowych informacji na temat samego posta.Komentarze

54,442 zapytań

98,327 odpowiedzi

202,258 komentarzy

26,743 pasjonatów

Przeglądających: 150
Pasjonatów: 4 Gości: 146

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto dwie polecane książki warte uwagi. Pełną listę znajdziesz tutaj.

...