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

Pytanie o zapis obiekt -> atrybut/metoda w Borland C++ Builder

Object Storage Arubacloud
+4 głosów
689 wizyt
pytanie zadane 16 lipca 2020 w C i C++ przez Young_engineer Początkujący (340 p.)
edycja 16 lipca 2020 przez Young_engineer
Mógłby ktoś mi wytłumaczyć dlaczego zapisuję się np. Label1 -> Visible = true zamiast Label1.Visible = true ?
1
komentarz 16 lipca 2020 przez Comandeer Guru (602,340 p.)
Proszę poprawić temat wątku na bardziej opisujący problem.

4 odpowiedzi

+4 głosów
odpowiedź 16 lipca 2020 przez Ilya Dimow Obywatel (1,240 p.)

a->b Jest używane tylko wtedy, gdy a jest wskaźnikiem. Jest to skrót dla (*a).b 

https://www.tutorialspoint.com/cplusplus/cpp_member_operators.htm

+4 głosów
odpowiedź 16 lipca 2020 przez VBService Ekspert (254,480 p.)
osoba *Karol = new osoba;

    // bez operatora strzalki

    (*Karol).wiek = 21;
    cout << (*Karol).wiek << endl;

    // z operatorem strzalki

    Karol->wiek = 21;
    cout << Karol->wiek << endl;

    delete Karol;

www.p-programowanie.pl - klasy cpp
Jak widzisz operator strzałki jest bardziej czytelny w przypadku dynamicznej alokacji. Posługując się standardowym operatorem kropki, należy dołączyć dodatkowe nawiasy. Wynika to z  faktu, że operator wyłuskania wskaźnika (gwiazdka) ma mniejszy priorytet niż operator kropki (odwołania się do składowej klasy).

+4 głosów
odpowiedź 16 lipca 2020 przez profesorek96 Szeryf (91,420 p.)
edycja 16 lipca 2020 przez profesorek96

W C++ mamy 4 rodzaje pamięci. Pamięć automatyczna, pamięć dynamiczna, pamięć statyczna oraz pamięć wątku.

Jeśli tworzysz zwykłą zmienną w ten sposób:

int a=5;

To ta zmienna należy do pamięci automatycznej. Cechuję ten rodzaj pamięci to że po wyjściu z bloku kody lub funkcji zmienna ta zostaje automatycznie usuwane. Nie ma to znaczenia czy tworzysz zmienną typu int czy obiekt klasy jeśli robisz to tak jak wyżej.

Zaś jeśli zrobisz tak:

int *a=new int;
*a=5;

To wtedy używasz pamięci dynamicznej. Pamięć ta cechuje się tym że tylko świadome wywołanie polecenia delete zwalnia tą pamięć. Ważne jest tutaj by nie zgubić wskaźnika na komórki pamięci zaalokowane w ten sposób. Jeśli nie zwolnili byśmy tej pamięci to mogło by dojść do wycieku pamięci tzw. Memory Leak.

Tyle wystarczy byś zrozumiał podstawy. Teraz zaś przejdźmy do twojego pytania.

Masz sobie klasę powiedzmy taką;

class Punkt2d
{
   public:
   int x,y;
};

Jeśli tworzę swój obiekt w ten sposób:

Punkt2d A;
A.x=5;

Czyli korzystam z pamięci automatycznej to jak najbardziej mogę odwoływać się do składowych przez operator kropki.

Jeśli zaś korzystam z tworzenia obiektów w sposób dynamiczny tak jak teraz:

Punkt2d *a=new Punkt2d;
A->x=5;

//pamietaj o zwalnianiu pamieci
delete a;

Jak widzisz korzystam z operatora strzałki (->) a nie jak poprzednio z kropki. Operator strzałki wprowadzono ponieważ wprowadza on pewien porządek.

Jeśli coś jest wskaźnikiem to, jak w naszym przypadku (zmienna a) jest to nic innego jak link prowadzący do adresu w pamięci. Teraz aby dostać się do wartości na jaką wskazuje musimy użyć operatora dereferncji czyli *. W dużym uproszczeniu można by było sądzić, że *a to to samo co A z przykładu o pamięci automatycznej. Oczywiście mówię, że to jest to samo pod względem tym że to są dwa obiekty tej samej klasy nie adres i obiekt. Jeśli jesteśmy już na tym samym poziomie to mogli byśmy teraz użyć operatora kropki.

*a.x=5

Jednak to co jest wyżej nie jest poprawne. Dlaczego zapytasz pewnie ?

Dzieje się tak dlatego że w cpp jest coś takiego jak priorytet operatorów. Operator kropki ma wyższy priorytet od *. Więc najpierw wykona się dostęp do składowej z pomocą kropki a dopiero później dereferencja. Jest to błedne w tym przypadku. Jeśli chcieli byśmy zmienić priorytet operatorów należy użyć nawiasów okrągłych.

(*a).x=5;
a->x=5;

Te dwa zapisu są sobie równoważne.

Na koniec zapraszam cię do przeanalizowania poniższego kodu:

#include <iostream>
using namespace std;

class A
{
	public:
	int *a;
	A()
	{
		a=new int;
	}
	~A()
	{
		delete a;
	}
};

int main() {
	A z;
	*z.a=5;
	cout<<z.a<<endl;
	cout<<*z.a<<endl;
	return 0;
}

Ukazuje on że zapis *z.a=5 jest w pewnych sytuacjach poprawny.

3
komentarz 16 lipca 2020 przez TOM_CPP Pasjonat (22,640 p.)

Używanie wskaźników w C++ może naprawdę prowadzić do skomplikowanych form. Dla klasy A z powyższego przykładu poprawny jest następujący kod:

 A**** z { new A*** { new A** { new A* { new A } } } };
 *(****z).a=5;
 cout << *(****z).a << endl;    

 

2
komentarz 16 lipca 2020 przez tkz Nałogowiec (42,000 p.)

@profesorek96,

W C++ mamy 4 rodzaje pamięci. Pamięć automatyczna, pamięć dynamiczna, pamięć statyczna oraz pamięć wątku.

No niezupełnie. Rodzaje mamy z 4, nie wgłębiając się za głęboko. Stos, sterta, bss i data. Ty wymieniłeś za to coś, co charakteryzuje czas życia, zasięg i łączenie zmiennych. 

 

Używanie wskaźników w C++ może naprawdę prowadzić do skomplikowanych form. Dla klasy A z powyższego przykładu poprawny jest następujący kod:

 A**** z { new A*** { new A** { new A* { new A } } } };
 *(****z).a=5;
 cout << *(****z).a << endl;   

Widziałeś gdzieś takie użycie? Pytam z czystej ciekawości. 

1
komentarz 16 lipca 2020 przez TOM_CPP Pasjonat (22,640 p.)
Nie i nigdy nie chciałbym zobaczyć. Moim celem było pokazanie na co pozwala struktura języka C++ i do czego może doprowadzić nadużywanie wskaźników.
+2 głosów
odpowiedź 16 lipca 2020 przez TOM_CPP Pasjonat (22,640 p.)

Gdyż Label1 jest wskaźnikiem do obiektu. Użycie wskaźnika wiąże się z koniecznością dostępu do zmiennych klasy przy użyciu operatora ->, lub też poprzez wyłuskanie wskaźnika za pomocą operatora dereferencji *.

class Label
{
public:
   int zmienna;
};

.....

Label *label1 = new Label();

label1->zmienna = 5;
(*label1).zmienna = 5;

delete label1;

 

komentarz 16 lipca 2020 przez Young_engineer Początkujący (340 p.)
Czyli obiekty w C++ Builder np. button  są bezimienne i dostaję się do nich przez wskaźniki?
komentarz 16 lipca 2020 przez j23 Mędrzec (194,920 p.)

Większość klas pochodnych od TComponent  jest i musi być tworzona na stercie, stąd te wskaźniki. To wymóg narzucony przez potrzebę zachowania zgodności z Delphi (bo w tym języku jest napisana biblioteka VCL).

Podobne pytania

0 głosów
3 odpowiedzi 292 wizyt
+1 głos
2 odpowiedzi 880 wizyt

92,632 zapytań

141,500 odpowiedzi

319,880 komentarzy

62,013 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!

...