Składowa klasy ktora jest dynamicznym obiektem

0

Z góry przepraszam bo nie wiedziałem co dokładnie wpisać w temacie.
Mam problem z paroma linijkami kodu niby wszystko działa ale problem w tym ze nie rozumiem paru zapisów. (po prostu wiem ze mam tak zrobić).

 adres a1(*wsk);   

; Tutaj podczas tworzenia nowego obiektu klasy adres inicjalizuję "konstruktor" wskaźnikiem ? Przecież nigdzie nie mam konstruktora w klasie adres który przyjmuje wskaźnik ?

 osoba():im("0"),naz("0"),wiek(0),wsk(new adres){};

Tutaj dlaczego nie mogę sobie zainicjalizować tym samym adresem na który wskaźnik pokazywał ? tylko używam operatora new i przydzielam nowy obszar pamięci?

osoba(const osoba &r):im(r.im),naz(r.naz),wiek(r.wiek),wsk(new adres(*r.wsk)){};

Natomiast tutaj tworze nowy obiekty typu adres i przypisuje wartosc na ktora pokazywal wczesniej wskaznik?

Miałem śmieszna anegdotkę na lekcji ze żona mojego kolegi to nie jest moja zona a jesli chce miec podobna to musze sobie znalezc blizniaczke bo ona jest już zajęta ;p

Teraz troszke inne pytanie : zna ktos z was anegdotkę o przeciazaniu operatora z jakims "tluczkiem do miesa" szukalem w google ? ale nic nie znalazlem .

Podsumowując (pytanie 2 i 3) tak jak to rozumiem to mam nie przypisywać tego samego adresu nowemu wskaznikowi w klasie osoba tylko stworzyć sobie nowy obszar pamięci i następnie dopiero wtedy przypisac nie adres a "wartosc" na ktora pokazywal "stary" wskaznik ? Ale dlaczego tak ?

  1. To co w kodzie jest w komentarzu to nie wiem czy akurat tam powinno być.. (braklo czasu na lekcji i tylko przepisałem) Wygląda mi to troche na przeciążenie operatora wyjścia ale ciało to bardziej mi przypomina konstruktor kopiujący ? najdziwniejsze mi sie wydaje return *this . Macie jakiś pomysł co do tego ? Na pewno jedna klasa miała właśnie mieć konstruktor kopiujący
 
#include <iostream>
#include <string>
using namespace std;

class adres
{
	string _miasto;
	string _kod;
	string _ulica;
	unsigned int _nr;

public:

	adres():_miasto(" brak "),_kod(" brak "),_ulica(" brak "),_nr(0){};
	adres(string a,string b,string c,unsigned int d):_miasto(a),_kod(b),_ulica(c),_nr(d){};
	friend ostream & operator <<(ostream & out,const adres& r);

};
	ostream & operator <<(ostream & out,const adres& r){
    out << r._miasto << r._kod << r._ulica << r._nr;
    return out;
    }
    
class osoba{
    string im,naz;
    unsigned wiek;
    adres *wsk;
public:
    osoba():im("0"),naz("0"),wiek(0),wsk(new adres){};
   osoba(const string& imie,const string& nazwisko,const unsigned &lata,const adres &a):im(imie),naz(nazwisko),wiek(lata),wsk(new adres){};

    osoba(const osoba &r):im(r.im),naz(r.naz),wiek(r.wiek),wsk(new adres(*r.wsk)){};
//   osoba & operator <<(ostream & out,const osoba& r){
     //if(this!=&r){
          //  im=r.im;
          //  maz=r.naz;
          //  wiek=r.wiek;
          //  *wsk= *r.wiek // SKOPIUJ WARTOSC NIE ADRES!
        //}
    //return *this;
    //};
};
int main()
{
	adres* wsk = new adres("Czestochowa", " 42-200", " Dabrowskiego ", 73);
	cout << *wsk << '\n'; // o co z tym chodzilo ?

	adres a1(*wsk);
	delete wsk;

	const adres* wsk1 = new adres("Warszawa", "00-950","Mysliwiecka", 357);
    cout << a1 << '\n';
    cout << *wsk1 << '\n';
    adres a2;
    cout << a2 << '\n';
    a2 = a1;
    cout << a2 << '\n';

    osoba o("Jan", "Kos", 25, *wsk1);

    delete wsk1;
    /*cout << o << '\n';
    osoba o1(o);
    cout << o1 << '\n';
    osoba o2;
    cout << o2 << '\n';
    o2 = o1;
    cout << o2 << '\n';*/

return 0;
}

 

Nie będę zamykać tematu póki co bo mam zamiar zrobić całe zadanie a zapewne będę musiał się was jeszcze o coś zapytać ;d

2

Krótkie powtórzenie ze wskaźników. Jeżeli mamy

int* wsk = new int;

to

  1. wsk jest wskaźnikiem i ma typ int*
  2. *wsk jest zmienną typu int na który wskazuje wsk.
adres a1(*wsk);

Korzystasz z konstruktora kopiującego, żeby kopiować obiekt, na który wskazuje wsk. Patrz punkt (2) wyżej.

osoba():im("0"),naz("0"),wiek(0),wsk(new adres){};

Tutaj dlaczego nie mogę sobie zainicjalizować tym samym adresem na który wskaźnik pokazywał?
Jakim adresem? Przecież tworzysz nowy obiekt i wsk nie wskazuje na nic sensownego.

osoba(const osoba &r):im(r.im),naz(r.naz),wiek(r.wiek),wsk(new adres(*r.wsk)){};

Chcesz mieć własny adres (własną żonę), dlatego tworzysz nowy obiekt typu adres. Chcesz, żeby początkowa wartość tego obiektu była taka sama jak obiekt na który wskazuje r.wsk (wyglądała tak samo jak żona kolegi), dlatego korzystasz z konstruktora kopiującego (bierzesz bliźniaczkę).

Ciało metody wygląda jak przeciążony operator=, więc nagłówek powinien wyglądać tak:

osoba& operator=(const osoba& r)
0

Czy to pelni role konstruktora kopiujacego i jednoczesnie przeciazenia znaku =

    
osoba & operator =(const osoba& r)
    {
     if(this!=&r){
     im=r.im;
     naz=r.naz;
     wiek=r.wiek;
     delete wsk;
     wsk=&r.wsk?new adres(*r.wsk):0; 
     }
   return *this;
   };

Dlaczego zwalniamy pamiec jak nowy obiekt klasy jest definiowany to tam nic nie powinno byc ?
if(this!=&r) po co taki warunek jest ?
Przeciez odbieramy przez referencje to robimy na orginale i dlaczego zwraccam wskaznik do this return *this ?

Zapomnialem wcześniej sie zapytać dlaczego przez referencje odbieramy argumenty ? (Czy to z tego samego powodu co obiekty klasy sa odbierane przez & )

osoba(const string& imie,const string& nazwisko,const unsigned &lata,const adres &a):im(imie),naz(nazwisko),wiek(lata),wsk(new adres){}; 
0

Podobne pytania pojawiały się już na tym forum milion razy. Szukaj wyjaśnienia pod hasłami: rule of three, copy&swap idiom, rule of zero.

1

Czy to pelni role konstruktora kopiujacego i jednoczesnie przeciazenia znaku =
Nie, to jest tylko przeciążony operator=.

Dlaczego zwalniamy pamiec
Bo ktoś nie wie co robi? Przecież w pierwszej wersji nie było żadnego delete.

if(this!=&r)

po co taki warunek jest?
Jeżeli masz bezsensowne przypisanie do samego siebie

obiekt = obiekt

to chcesz, żeby operator przypisania nic nie robił.

dlaczego zwraccam wskaznik do this

return *this;

Nie wskaźnik, tylko referencję do obiektu. By móc łańcuchowo przypisać

obiekt1 = obiekt2 = obiekt3

Zapomnialem wcześniej sie zapytać dlaczego przez referencje odbieramy argumenty ?
Przekazujemy argumenty przez referencję, by ich nie kopiować. Jeżeli argumentem jest duży obiekt, to takie kopiowanie może być bardzo kosztowne. A const jest po to, by zabronić modyfikacji tych argumentów (jeżeli jednak ktoś chce zmodyfikować taki przekazany argument, to oczywiście wtedy jest referencja bez const).

0

Ktory fragment kodu bylby lepszy ? i po czym posprztac po calym obiekcie ? czy po dynamicznej obiekcie typu adres ?

 
    osoba& operator = (const osoba& os){
        if(this!=&os)  
        imie = os.imie;
        nazwisko = os.nazwisko;
        wiek = os.wiek;
        *adr = *os.adr;
        return *this; 
    }

    ~osoba(){
    cout << "sprzatam, bo lubie" << endl;
    }

Kontra ten fragment kodu (W tym wypadku zwalniamy pamiec z dynamicznego obiektu adres i za pomoca destruktora czyscimy. )
```cpp
osoba& operator=(const osoba& os)
        {
            if(this!=&os)
            {
                imie=os.imie;
                nazwisko=os.nazwisko;
                wiek = os.wiek;
                delete adr;
                adr = &org.adr ? new adres(*org.adr):0; 
            }            
            return *this;   
        }
        ~osoba() {delete adr;}
 

Lepiej uzyc warunku ternarnego?

  adr = &org.adr ? new adres(*org.adr):0;

czy po prostu przypisac to na co pokazuje wskaznik drugiemu wskaznikowi ?

 *adr = *os.adr; 
1

A po co chcesz zwalniać pamięć i zarezerwować nową? Czy to coś daje oprócz marnowania czasu procesora?

~osoba()
{
    cout << "sprzatam, bo lubie" << endl;
}

wyciek pamięci, bo nie zwalniasz adr

adr = &org.adr ? new adres(*org.adr):0;

Dosyć poważny błąd. org.adr jest adresem i chcesz sprawdzić wartość tego wskaźnika, która jest adresem innego obiektu, a nie adresu tego wskaźnika.

Korzystaj z formatera, bo masz dosyć lewe wcięcia: http://format.krzaq.cc
I korzystaj z opcji Pogląd przed wysłaniem posta.

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