• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Obiekty w c++ przypisanie obiektów i odniesienie do javy

Object Storage Arubacloud
0 głosów
854 wizyt
pytanie zadane 30 czerwca 2016 w C i C++ przez itcloud Gaduła (3,380 p.)
edycja 30 czerwca 2016 przez Patrycjerz

Mam problem już na samym początku, poniżej niby banalny kod:

class Example{
public:    int c;
};

int main()
{
    Example t1 = new Example();
    t1.c = 222;
    cout << t1.c << endl;
    return 0;
}

1. Kompilator zwraca błąd: error: conversion from 'Example*' to non-scalar type Example requested - why??

2. Chciałem w tym prostym kodzie sprawdzić, jak wygląda przypisywanie obiektów np. tworzę obiekt t1 typu Example jak wyżej i obiekt t2 analogicznie a potem piszę:t1.c = t2.c  i podobno w Javie jest tak, że jest to przypisanie referencji, a jak jest w c++?

1 odpowiedź

0 głosów
odpowiedź 30 czerwca 2016 przez Yiome Obywatel (1,000 p.)
edycja 30 czerwca 2016 przez Patrycjerz

[1]

#include <iostream>

class Example
{
public:
    int c;
};

int main()
{
    Example *t1 = new Example(); //t1 musi być wskaznikiem
    t1->c = 222; // i operator wyłuskania [ . ]  przy wskaznikach wygląda tak [ -> ]
    std::cout << t1->c <<std::endl;
    return 0;
}
komentarz 30 czerwca 2016 przez itcloud Gaduła (3,380 p.)

OOO, dziękować:) Możesz w krótkich zdaniach wyjasnić, czemu to musi być wskaźnik?

W przykładzie z "Thinking in java":

dwie klasy t1 i t2 typu Tank np.:

Tank t1 = new Tank();

Tank t2 = new Tank();

t1.level = 9; t2.level = 47;

i potem jest przypisanie: t1 = t2     (tutaj nie ma niby niespodzianki, bo od teraz wypisanie t1.level   i t2.level   daje dla obu wartości 47, 47

ale dalej:  t1.level=27

i od teraz t1.level   i t2.level mają wartości 27. A nie tylko t1.level.

W c++ jest podobnie. Lekko przerobiłem Twój kod i też dziwny wynik:

#include <iostream>

using namespace std;

class Example
{
public:
    int c;
};

int main()
{
    Example *t1 = new Example(); //t1 musi być wskaznikiem
    t1->c = 222;

    Example *t2 = new Example();
    t2->c = 333;

    t1->c = t2->c;

    t1 = t2;
    t1->c = 444;

    std::cout << t1->c <<std::endl;
    std::cout << t2->c <<std::endl;
    return 0;
}

 

komentarz 30 czerwca 2016 przez John Doe Obywatel (1,720 p.)

Używając operatora new, przydzielasz pamięć dynamicznie - ze sterty. Potrzebujesz czegoś, czym mógłbyś odwoływać się do takiego bloku pamięci - w C++'ie, od tego masz wskaźnik.

Ponadto, zapis t1->c jest równoważny (*t1).c. Jest to po prostu ładniejsza forma tego drugiego zapisu, gdzie najpierw przeprowadzone jest wyłuskanie (gwiazdka i nazwa obiektu), a następnie odwołanie do składowej (kropka i nazwa składowej).

komentarz 30 czerwca 2016 przez John Doe Obywatel (1,720 p.)
1) t1->c = t2->c;
2) t1 = t2; 
3) t1->c = 444;

W pierwszej linijce przypisujesz wartość składowej c obiektu wskazywanego przez t2, do odpowiadającej jej składowej obiektu wskazywanego przez t1 - w porządku. 

W drugiej linijce przypisujesz adres, na który wskazuje wskaźnik t2, do wskaźnika t1 - nie w porządku. Nie zdealokowałeś pamięci (operatorem delete), którą wskazywał wskaźnik t1, przez co, gdzieś tam wciąż istnieje pamięć, z której korzysta program, ale nie masz do niej dostępu (memory leak). Doprowadziłeś natomiast do tego, iż t1 oraz t2 wskazują na jeden i ten sam blok pamięci.

Więc przypisując, w linijce trzeciej, 144 do składowej c obiektu wskazywanego przez t1, przypisujesz także tę wartość do obiektu wskazywanego przez t2 - bo od drugiej linijki, oba wskaźniki, wskazują na ten sam obiekt.

Przeprowadzając drugą operację w następujący sposób: *t1 = *t2 - dokonasz płytkiej kopii obiektu t2, przypisując go do t1, co w przypadku tego jednego int'a powinno być wystarczające.

komentarz 30 czerwca 2016 przez itcloud Gaduła (3,380 p.)
John Doe - dzięki wielkie, bardzo fajnie to wytłumaczyłeś. Faktycznie, ta druga linijka szczególnie w c++ nie jest ok - inaczej w javie, bo tam jest garbage collector.
komentarz 30 czerwca 2016 przez John Doe Obywatel (1,720 p.)

Proszę bardzo. Czy fajnie wytłumaczyłem, to nie wiem - gdybym dopiero się uczył, to uznałbym to, co napisałem, za bełkot :).

 inaczej w javie, bo tam jest garbage collector.

Tak też słyszałem, że zarządzanie pamięcią w Javie jest cudowne. Czytałem również, że nie należy przenosić żadnych technik programowania między Javą i C++, ale nie mnie to osądzać. Pozdrawiam.

komentarz 30 czerwca 2016 przez adrian17 Ekspert (344,860 p.)

Nikt chyba nie wspomniał, ale:

Możesz w krótkich zdaniach wyjasnić, czemu to musi być wskaźnik?

Nie musi.

int main()
{
    Example t1;
    t1.c = 222;
    cout << t1.c << endl;
    return 0;
}
komentarz 1 lipca 2016 przez John Doe Obywatel (1,720 p.)
edycja 1 lipca 2016 przez John Doe

Racja. Założyłem ad hoc, że itcloud potrzebuje dynamicznej alokacji.

Podobne pytania

0 głosów
1 odpowiedź 1,805 wizyt
0 głosów
1 odpowiedź 146 wizyt

92,579 zapytań

141,429 odpowiedzi

319,657 komentarzy

61,962 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...