Obiekt dynamiczny w klasie i nie dzialajacy konstruktor przypisujacy

0

Witam nie udało mi się zrobić poprawnie konstruktora kopiującego w klasie osoba. Próbowałem zaprzyjażnic klase data z osoba by mięć dostęp do prywatnych pol . Niestety w konstruktorze kopiującym nie mogę się odwołać do tych "prywatnych pol klasy data" co skutkuje tym ze nie rusza konstruktor przypisujący w klasie data .

#include <iostream>

using namespace std;
class osoba;
class data{
    
    string im,naz;
    int wi;
public:
    friend class osoba;
    data():im("brak"),naz("brak"),wi(0){}
    data(const string&i,const string&n,const int l):im(i),naz(n),wi(l){}
};
class osoba{
    data* dane;
public:
    osoba():dane(new data){}
    osoba(const string& name,const string& surname,const int age):dane(new data(name,surname,age)){}
    osoba(const osoba& ob):dane(new data(ob.im,ob.naz,ob.wi)){} // tutaj problem

};
int main()
{
    osoba o1,o2;
    const osoba * wsk1 = new osoba("Ala","Koala",15);
    const osoba o3(*wsk1);
    delete wsk1;
    wsk1=0;
    const osoba* wsk2 = new osoba(o3);// tutaj problem
    return 0;
}

 
1

Niech klasa data ma własny konstruktor kopiujący i wtedy osoba nie musi mieć dostępu do niczego bo całą robotę wykona ten konstruktor.

Bawiąc się wskaźnikami pamiętaj, że łatwo o wyciek pamięci, co widać w Twoim kodzie. Nie usunąłeś pamięci, na którą wskazuje dane i już przypisujesz do niego nową wartość.

0

Dzięki :)

0

Niestety znowu napotkałem problem tym razem podczas przeładowania operator wyjścia chciałem wyrzucić na ekran informacje o obiekcie dlatego zaprzyjazniłem klase niestety jak widać nie mam dostępu do pol prywatnych mimo ze zaprzyjaznilem klasy. (nie chce za pomocą metod dostepowych tego robic).

 
#include <iostream>

using namespace std;
class osoba;
class data{

    string im,naz;
    int wi;
public:
    friend class osoba;
    data():im("brak"),naz("brak"),wi(0){}
    data(const string&i,const string&n,const int l):im(i),naz(n),wi(l){}
    //data(const data& ob):im(ob.im),naz(ob.naz),wi(ob.wi){}
};
class osoba{
    data* dane;
public:
    osoba():dane(new data){}
    osoba(const string& name,const string& surname,const int age):dane(new data(name,surname,age)){}
    osoba(const osoba& ob):dane(new data(*ob.dane)){}
    osoba& operator=(const osoba& obiekt){
        if(this!=&obiekt)
        {
            delete dane;
            dane = new data(*obiekt.dane);
            return *this;
        }
    }
    friend ostream& operator << (const ostream& out,const osoba& ob);
    ~osoba(){delete dane;}

};
    ostream& operator << (const ostream& out, const osoba& ob){
        out << ob.im << " " << ob.naz << " " << ob.wi << endl;
        return out;
    }
int main()
{
    osoba o1,o2;
    const osoba * wsk1 = new osoba("Ala","Koala",15);
    const osoba o3(*wsk1);
    delete wsk1;
    wsk1=0;
    const osoba* wsk2 = new osoba(o3);
    o2=*wsk2;
    cout << o1 << *wsk2;
    return 0;
}

1

Po pierwsze: zawsze wklejaj komunikaty błędów. A stawiam moją licencję wróżbity, że tam nic nie ma o dostępie do prywatnych danych, tylko o to:

ostream& operator<<(const ostream& out

Przecież zmieniasz ten strumień, więc jak niby możesz go przekazać jako const?

0

Zapomnialem to zmienic ale mimo wszystko i tak po usunieciu consta nadal wyskakuje :
In function 'std::ostream& operator<<(std::ostream&, const osoba&)':|
|34|error: 'const class osoba' has no member named 'im'|
|34|error: 'const class osoba' has no member named 'naz'|
|34|error: 'const class osoba' has no member named 'wi'|
== Build failed: 3 error(s), 0 warning(s) (0 minute(s), 0 second(s)) ===

1

To, że zadeklarowałeś przyjaźń nie znaczy, że osoba przejmuje pola klasy data
W operatorze powinieneś odwoływać się do klasy data

    ostream& operator << (const ostream& out, const osoba& ob){
        out << ob.dane->im << " " << ob.dane->naz << " " << ob.dane->wi << endl;
        return out;
    }

Na przyszłość też staraj się, w kodzie, nie mieszać polskiego i angielskiego. Pisz od razu po angielsku

1

No przecież kompilator jasno Ci mówi:
klasa osoba nie ma pól o nazwach im, naz, wi

To, że klasa osoba ma dostęp do tych pól w klasie data poprzez przyjaźń nie znaczy, że one będą polami klasy osoba.
Na oko to powinieneś przeciążać operator<<(ostream&, const data&), a potem wystarczy

ostream& operator<<(ostream& out, const osoba& o)
{
    out << *o.dane;
    return out;
}
0

Dziekuje wam :)

0

Znowu pojawił mi się kolejny problem tym razem z operatorem wejscia.
Probowałem coś odczytac z pliku i nastepnie wpisac to do pomocniczej zmiennej typu string, by później moc przypisać odczytana wartość z pliku, do tablicy obiektów klasy osoba odebraną poprzez wskaźnik w funkcji wczytaj . W tym celu przeładowałem operator węjscia.

Przy użyciu tego zapisu **tab[i] = tekst *nie kompiluję się.
To wywala kompilator
In function 'void wczytaj(const osoba
, int, const string&)':
|72|error: no match for 'operator=' in '*(tab + ((sizetype)(((unsigned int)i) * 4u))) = tekst'|
|72|note: candidate is:|
|40|note: osoba& osoba::operator=(const osoba&)|
|40|note: no known conversion for argument 1 from 'std::string {aka std::basic_string<char>}' to 'const osoba&'|
== Build failed: 1 error(s), 0 warning(s) (0 minute(s), 0 second(s)) ===

Plik textowy wygląda mniej wiecej tak:
imie nazwisko wiek
imie nazwisko wiek
imie nazwisko wiek
imie nazwisko wiek

#include <iostream>
#include <fstream>
using namespace std;
class osoba;
class data{
    string im,naz;
    int wi;
public:
    friend class osoba;
    data():im("brak"),naz("brak"),wi(0){}
    data(const string&i,const string&n,const int l):im(i),naz(n),wi(l){}

    friend ostream& operator << (ostream& out , const data& ob){
        out << ob.im << " " << ob.naz << " " << ob.wi;
        return out;
    }
    string& imie(){return im;}      
    string& nazwisko(){return naz;}       
    int& wwiek(){return wi;}       
    const int& wwiek()const{return wi;}

};
class osoba{
    data* dane;
public:
    osoba():dane(new data){}
    osoba(const string& name,const string& surname,const int age):dane(new data(name,surname,age)){}
    osoba(const osoba& ob):dane(new data(*ob.dane)){}
    osoba& operator=(const osoba& obiekt);
    friend ostream& operator << (ostream& out,const osoba& ob);
    ~osoba(){delete dane;}
    osoba& operator+(int l);

    friend istream& operator >> (istream& in , osoba& ob){
        in >> ob.dane->imie() >> ob.dane->nazwisko() >> ob.dane->wwiek();
        return in;
    }
};

osoba& osoba::operator=(const osoba& obiekt)
{
    if(this!=&obiekt)
    {
        delete dane;
        dane = new data(*obiekt.dane);
        return *this;
    }
}

ostream& operator << (ostream& out, const osoba& ob)
{
    out << *ob.dane << endl;
    return out;
}

osoba& osoba:: operator +(int l)
{
    (*dane).wwiek()+=l;
    return *this;
}

void wczytaj(const osoba* tab,int r,const string& naz) throw (string)
{
    ifstream plik(naz.c_str());
    string tekst;
    if(!plik) throw string ("Nie udalo sie otworzyc pliku");
    else
    {
        for(int i = 0 ; i < r ; i++)
        {
            plik >> tekst;
          //  tab[i] = tekst;

        }

    }
}
 

int main()
{
    osoba o1,o2;
    const osoba * wsk1 = new osoba("Ala","Koala",15);
    const osoba o3(*wsk1);
    delete wsk1;
    wsk1=0;
    const osoba* wsk2 = new osoba(o3);
    o2=*wsk2;
    cout << o1 << *wsk2;
    delete wsk2;
    cout << o2;
    cout << o2 + 10;
    cout << "************\n";
    osoba tab[4];
    try{
        wczytaj(tab,4,"data.txt");
    }
    catch (const string& err){cout << err << endl;}
    return 0;
}

0

tab[i] to obiekt typu osoba (konkretnie to const osoba&), tekst to std::string, skąd kompilator ma wiedzieć jak przypisać string do osoba?

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