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.

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