Kostruktor kopiujący

0

Witam,
Przy pisaniu programu napotkałem na nieścisłość tj. kopiowanie agregatu w konstruktorze kopiującym.
Moje pytanie brzmi : "Czy takie kopiowanie jest poprawne ? Gdy usune gwiazdki pokazuje błąd pamięci i nie wiem w czym problem tzn. na jakiej zasadzie to działa, czy kopiujemy sam adres ?" Czekam na podpowiedzi i z góry dziękuje ;)
Fragment kodu :
A::A(A& wzor) : pi(3.14)
{
this->liczbaA = wzor.liczbaA;
this->agr1 = new B;
*(this->agr1) = *(wzor.agr1);
}

0

jeżeli agr1 to jest wskaźnik na coś to linijka:

*(this->agr1) = *(wzor.agr1);

oznacza przypisanie do zmiennej wskazywanej przez wskańnik agr1 wartości znajdującej się pod adresem wskazywanym przez wzor.agr1

usunięcie operatora dereferencji (gwiazdki) oznacza przypisanie adresu przechowywanego w wzor.agr1 do pola agr1. Teraz te 2 obiekty będą korzystać z tego samego adresu. Zakładając, że w destruktorze robisz delete agr1; to będzie to wywołane dwa razy dla tego samego adresu.

1

powinno być raczej (zgaduje):

A::A(A& wzor) : pi(3.14)
{
        this->liczbaA = wzor.liczbaA;
        this->agr1 = new B(*(wzor.agr1)); // stwórz kopię tego na co wskazuje wzor.agr1
}
0

Karolaq super że wytłumaczyłeś jeszcze chciałem dopytać, bo w agr1(agregat innej klasy) mam kilka innych składników. Teraz pytanie czy mogę kopiować wszystko tak jak to zrobiłem i będą przekopiowane wszystkie składniki agregatu czy tylko pierwszy bo na niego pokazuje adres ? czy tez muszę dopisywać metody do klasy z której pochodzi agr1 i wywołać np. w taki sposób this->agr1->ustaw(wzor.agr1->zwroc()); ?
I jesli moglbys odniesc sie do poprzednika bo taki kod sie kompiluje ale nie mam pewnosci co do poprawnosci dzieki bardzo za pomoc :)

0

To zależy od tej klasy B. W linijce:

*(this->agr1) = *(wzor.agr1);

korzystasz z operatora przypisania. Jeżeli samemu go nie implementowałeś, kompilator zrobił to za Ciebie. Jego działanie będzie takie, że każde pole obiektu klasy B będzie przekopiowane z analogicznego pola obiektu, który jest przypisywany. Inaczej mówiąc, każde pole z *(wzor.agr1) będzie poprawnie przypisane do odpowiednich pól w *(this->agr1). Tylko uwaga, trzeba wiedzieć co to znaczy przypisanie w przypadku danego typu. np std::vector zostanie przekopiowany w porządany sposób, a normalna tablica (tj. wskaźnik na pierwszy element tablicy) już raczej nie.
Jeżeli samemu pisałeś operator przypisania, wtedy to już zależy, jak to zrobiłeś :)

Kod podany przez Marka różni się tym, że on wykorzystuje konstruktor kopiujący klasy B. I tu jest tak samo: albo napisałeś samemu taki konstruktor albo zrobił to kompilator.
Zasadniczo ta wersja jest lepsza i może nawet szybsza. W praktyce będzie to zależało do typu pól składowych. Ale i tak myślę, że dobrym nawykiem będzie korzystanie z tego rozwiązania.

0

Ok, bardzo wyczerpująca odpowiedź. Wnioskuje że najlepszym nawykiem będzie tu napisanie własnego konstruktora kopiującego w obydwu klasach i uruchomienie go w klasie agregujacej obiekt. Rozumiem że z operatorem przypisania sprawa wygląda identycznie. Jeżeli mielibyśmy tablicę w klasie jak wspomniałeś wcześniej to wtedy kopiowanie adresu przy automatycznym konstruktorze kopiujacym bądź operatorze przypisania może nie odbyć się tak jak byśmy sobie tego życzyli ? Gdy napiszemy sami wtedy mamy pewność że operacja zakończy się pomyślnie. Dobrze rozumuje ?

0

pi(3.14)

jakiś powód, by używać niedokładnej wartości, podczas gdy w bibliotece standardowej jest zdefiniowana wartość dużo bliższa prawdy?

0

Azarien jakoś nie mogę wyciągnąć tej wartości w visual studio 2010 natomiast w Dev-Cpp jak najbardziej. Nie wiem gdzie leży problem. Jakieś sugestie ?

0
#include <iostream>
#include <cmath>
using namespace std;
int main(){
    cout<<"Wartosc liczby 'pi' wynosi: "<<M_PI<<endl;
    cout<<"Wartosc liczby 'e' wynosi:"<<M_E<<endl;
    return 0;
}
0

To rozwiązanie, które podałeś nie działało, lecz znalazłem właściwe :

#include <iostream>
#define _USE_MATH_DEFINES
#include <math.h>
using namespace std;
int main(){
cout<<"Wartosc liczby 'pi' wynosi: "<<M_PI<<endl;
cout<<"Wartosc liczby 'e' wynosi:"<<M_E<<endl;
system("pause");
return 0;
}

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