• 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ść )

VPS Starter Arubacloud
+1 głos
340 wizyt
pytanie zadane 14 czerwca 2018 w C i C++ przez Jakub 0 Pasjonat (23,120 p.)
zamknięte 14 czerwca 2018 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 2018 przez Jakub 0 Pasjonat (23,120 p.)
Jeżeli pytanie jest nie jasne  to będę wdzięczny za info, bo coś cisza :/
komentarz 14 czerwca 2018 przez RafalS VIP (122,820 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 2018 przez Jakub 0 Pasjonat (23,120 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 2018 przez monika90 Pasjonat (22,940 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 2018 przez Jakub 0 Pasjonat (23,120 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 2018 przez RafalS VIP (122,820 p.)
Rozpisze Ci to dzis wieczorem jak bd mial dostep do klawiatury a nie ekranu tel :p
komentarz 14 czerwca 2018 przez RafalS VIP (122,820 p.)
Edytowałem odpowiedz, bo do komentarzy nikt nie patrzy, a może komuś się to przyda.

1 odpowiedź

0 głosów
odpowiedź 14 czerwca 2018 przez RafalS VIP (122,820 p.)
edycja 14 czerwca 2018 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 2018 przez Jakub 0 Pasjonat (23,120 p.)
edycja 14 czerwca 2018 przez Jakub 0
Ale gdyby sygnatury funkcji były takie same to trzeba by było dać ten operator jako wirtualny?
komentarz 14 czerwca 2018 przez Jakub 0 Pasjonat (23,120 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 2018 przez RafalS VIP (122,820 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 2018 przez Jakub 0 Pasjonat (23,120 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ź 213 wizyt

92,453 zapytań

141,262 odpowiedzi

319,088 komentarzy

61,854 pasjonatów

Motyw:

Akcja Pajacyk

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

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Akademia Sekuraka 2024 zapewnia dostęp do minimum 15 szkoleń online z bezpieczeństwa IT oraz dostęp także do materiałów z edycji Sekurak Academy z roku 2023!

Przy zakupie możecie skorzystać z kodu: pasja-akademia - użyjcie go w koszyku, a uzyskacie rabat -30% na bilety w wersji "Standard"! Więcej informacji na temat akademii 2024 znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...