konstruktor kopiujący

0

Hej! Powracam z pytaniem odnośnie konstruktora. Próbuję zaimplementować konstruktor kopiujący, który po wywołaniu zwróci mi skopiowany obiekt i wyświetli informacje o swoim typie. Niestety po wywołaniu konstruktor wyświetla tyko informacje o tym, że jest kopiujący natomiast nie zwraca kopiowanego obiektu. Czy znajdzie się tutaj dobra dusza, która wytłumaczy mi jakoś przystępnie jak z niego korzystać i dlaczego w moim przypadku nie działa on poprawnie?

KLASA ItSpecialist

class ItSpecialist : protected Worker
{
	std::string ifpc;
	bool pc = 1;
public:
	ItSpecialist(const ItSpecialist &itspecialist)
	{
		std::cout << " Kopiujacy" << std::endl << " z klasy ItSpecialist " << std::endl << std::endl;
	}

	ItSpecialist(double salary, std::string name, std::string surname) : Worker(salary* RandCost(2, 7), name, surname)
	{
		pc = RandCost(1, 2);
		if (pc)
		{
			salary = salary - 120 * RandCost(2, 7);
			ifpc = "TAK";
		}
		else
		{
			ifpc = "NIE";
		}

		std::cout << " Sparametryzowany" << std::endl << " z klasy ItSpecialist " << std::endl << std::endl;
		std::cout << getName() << " " << getSurname() << std::endl;
		std::cout << " Czy posiada komputer? " << ifpc << std::endl;
		std::cout << " W sumie zarabia: " << salary << " brutto" << std::endl << std::endl;
	}
};

MAIN

int main()
{
// ...Spar - Sparametryzowany | ...Domy - Domyslny | ...Kopi - Kopiujący 

	srand(time(NULL));

	ItSpecialist* itspecialistSpar = new ItSpecialist(6000, " Hacker", "Bonzo");
	delete itspecialistSpar;
	Sleep(1000);

	ItSpecialist itspecialistKopi = *itspecialistSpar;

	getchar();
	return 0;
}

Dziękuję pięknie za każdą podpowiedź

2

Musisz zaimplementować ten proces kopiowania, w konstruktorze kopiującym - samo nie zadziała.
Inną rzeczą jest, że wywołałeś operator = (który wywoła konstruktor kopiujący), pomijając fakt, że próbujesz przypisać obiekt, który wcześniej usunąłeś.

Istnieją dwa typy konstruktorów kopiujących - shallow copy/deep copy. Generalnie, materiałów na ten temat jest masa, więc nie będę się powtarzać, a jedynie podlinkuję pierwszy link z googla np.: LINK

W skrócie:
Wyobraź sobie obiekt, który posiada wskaźnik na np. ciąg znaków (char *). Wskaźnik wskazuje na konkretny adres w pamięci, gdzie znajduje się twój ciąg znaków. Płytka kopia, to stworzenie obiektu, który będzie wskazywać na ten sam obszar pamięci (ten sam ciąg znaków). Jeżeli jeden z nich go usunie, drugi w tym momencie wskazuje na nieistniejący już obszar pamięci - co jest błędem. Deep copy, czyli kopia głęboka, w tym wypadku alokuje miejsce na nowy ciąg znaków i kopiuje jego zawartość w to miejsce. Oba obiekty, mają swoją kopię stringa, nie ma ryzyka, że jeden zwolni drugiemu ten zasób.

1

Konstruktor nic nie zwraca, w sensie returen'a...

Po drugie: skąd z Twojego main'a wiesz, że nic nie zwraca...?

Po trzecie: chodzi Ci nie o zwracanie, tylko skopiowanie elementu do nowego obiektu, a tego po prostu nie robisz! Dopisz : ifpc(itspecialist.ifpc), pc(itspecialist.pc) między 6. a 7. linią klasy (jeśli się nie machnąłem)...

2
wyebani napisał(a):

Inną rzeczą jest, że wywołałeś operator =, pomijając fakt, że próbujesz przypisać obiekt, który wcześniej usunąłeś.

Mylisz się, linia 11. main'a to konstruktor kopiujący.

0

Opisz co chciałeś osiągnąć w main().
To przypisanie usuniętego wcześniej obiektu nieciekawie wygląda.

Konstruktor kopiujący dostaje w parametrze obiekt który musi skopiować czyli przypisać do własnych pól wartości z tego kopiowanego obiektu. Twój konstruktor jedynie wypisuje tekst. Uzupełnij go i będzie działać. Od C++11 możesz użyć constructor chaining co uprości sprawę.

0

Nie możesz zrobić *itspecialistSpar ani itspecialistSpar-> po tym jak zrobiłeś delete itspecialistSpar.

1

Jak sam nazwa wskazuje konstruktor kopiujący musi coś kopiować - w tym wypadku będzie to kopia obiektu itspecialist.

ItSpecialist( const ItSpecialist &itspecialist )
: Worker { itspecialist }, ifpc { itspecialist.ifpc }, pc { itspecialist.pc }
{
}

Zauważ, że powyższy konstruktor w swoim zachowaniu niczym nie różni się od swojej domyślnej wersji stworzonej przez kompilator.
Można więc śmiało zamienić na:

ItSpecialist( const ItSpecialist &itspecialist ) = default;

Własna implementacja konstruktora kopiującego potrzebna jest między innymi wtedy gdy niezbędna jest tzw. deep copy obiektu.

0
TomaszLiMoon napisał(a):

Zauważ, że powyższy konstruktor w swoim zachowaniu niczym nie różni się od swojej domyślnej wersji stworzonej przez kompilator.
...
Własna implementacja konstruktora kopiującego potrzebna jest między innymi wtedy gdy niezbędna jest tzw. deep copy obiektu.

U niego się różni, bo musiał coś wyświetlić dodatkowo, więc nici z default tutaj...

0

Kurcze, wiele mądrych rzeczy dowiedziałem się dzięki Wam. Bardzo dziękuję za wszystkie wskazówki i pomoc. :) Niestety problem wciąż nie został rozwiązany. Może zacznę od początku, tak będzie najprościej.
Dostałem na studiach ćwiczenie do zrealizowania żeby lepiej zrozumieć działanie konstruktorów i destruktorów. Zadanko wygląda tak:
title

W mainie chciałbym wywołać konstruktor kopiujący, który skopiuje mi obiekt itspecialist i dopisze, że jest to właśnie konstruktor kopiujący. Usunąłem destruktor żeby wskaźnik nie wskazywał na puste miejsce w pamięci, zastosowałem się też do Waszych wskazówek wyżej, niestety i to nie pomogło. I kurcze nie do końca wiem dlaczego to nie działa.

Bo jak rozumiem konstruktor kopiujący tworzymy w taki sposób:

   Konstruktor(int x1, int y1) 
{ 
x = x1; 
y = y1;
 } 
   Konstruktor(const Konstruktor &k2)
 {
x = k2.x; 
y = k2.y; 
} 

Konstruktor k1(20, 30);
Konstruktor k2 = k1;
0

Łatwiej będzie nam pomóc, jak pokażesz niedziałający kod razem z wyświetlanymi przez kompilator błędami.

0

Dziękuję wszystkim pięknie za pomoc. Ostatecznie udało mi się zrozumieć istotę problemu. Mój konstruktor kopiujący działał, natomiast chciałem pokazać coś co by się i tak nie wyświetliło.
Rozwiązaniem było wykonanie na siłę innego konstruktora w konstruktorze kopiującym.

	ItSpecialist(const ItSpecialist& itspecialist) : ItSpecialist(itspecialist.salary, itspecialist.name, itspecialist.surname)
	{
		pc = itspecialist.pc;
		ifpc = itspecialist.ifpc;
		std::cout << " Kopiujacy" << std::endl << " z klasy ItSpecialist " << std::endl << std::endl;

	}

Niemniej dziękuję jeszcze raz za pomoc. Na pewno wyniosę wiele wartościowych uwag i wiedzy z Waszej pomocy. Pozdrawiam :)

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