Wprowadzenie do klas i obiektów w C ++

01

z 09

Począwszy klasy C ++

Ręce, wpisując na laptopie
Sam Edwards / Getty Images

Obiekty są największą różnicą między C ++ i C. Jedną z najwcześniejszych nazw dla C ++ było C z klasami.

Klasy i przedmioty

Klasa jest definicją obiektu. To taki typ int. Klasa przypomina a struct z jedną różnicą: domyślnie wszyscy członkowie struktury są publiczni. Wszyscy członkowie klas są prywatni.

Pamiętaj - klasa jest typem, a przedmiotem tej klasy jest po prostu zmienna.

Zanim będziemy mogli użyć obiektu, należy go utworzyć. Najprostsza definicja klasy to:

 Nazwa klasy {

 // członkowie

 }


Ta przykładowa klasa poniżej modeluje prostą książkę. Korzystanie z OOP pozwala wyodrębnić problem i pomyśleć o nim, a nie tylko dowolne zmienne.

 // przykład pierwszy

 #zawierać 

 #zawierać 


 klasa Book

 {

 int PageCount;

 int CurrentPage; 

 publiczny:

 Książka (int Numpages); // Konstruktor

 ~ Book () {}; // Niszczyciel

 void SetPage (int PageNumber);

 int GetCurrentPage (void);

 }; 


 Book:: Book (int NumPages) {

 PageCount = NumPages;

 }


 void Book:: SetPage (int PageNumber) {
instagram viewer

 CurrentPage = Numer strony;

 }


 int Book:: GetCurrentPage (void) {

 zwróć CurrentPage;

 }


 int main () {

 Książka ABook (128);

 Książka. SetPage (56);

 std:: cout << „Bieżąca strona” << ABook. GetCurrentPage () << std:: endl;

 zwraca 0;

 }


Cały kod z książka klasowa aż do int Book:: GetCurrentPage (void) { funkcja jest częścią klasy. The Główny() istnieje funkcja umożliwiająca uruchomienie tej aplikacji.

02

z 09

Zrozumienie klasy książki

w Główny() funkcja tworzy zmienną ABook typu Book o wartości 128. Jak tylko wykonanie osiągnie ten punkt, obiekt ABook jest konstruowany. W następnym wierszu metoda Książka. SetPage () jest wywoływana, a wartość 56 przypisywana do zmiennej obiektowej Książka. Bieżąca strona. Następnie cout wypisuje tę wartość przez wywołanie Książka. GetCurrentPage () metoda.

Kiedy wykonanie osiągnie zwraca 0; obiekt ABook nie jest już potrzebny aplikacji. Kompilator generuje wywołanie do destruktora.

Deklarowanie klas

Wszystko pomiędzy Klasa Book i } jest deklaracją klasy. Ta klasa ma dwóch członków prywatnych, oba typu int. Są one prywatne, ponieważ domyślny dostęp do członków klasy jest prywatny.

The publiczny: dyrektywa mówi kompilator dostęp z tego miejsca jest publiczny. Bez tego nadal byłby prywatny i uniemożliwiałby trzem wierszom funkcji main () dostęp do członków Abook. Spróbuj komentować publiczny: wyloguj się i przekompiluj, aby zobaczyć wynikające z tego błędy kompilacji.

Ta linia poniżej deklaruje konstruktora. Jest to funkcja wywoływana przy pierwszym tworzeniu obiektu.

 Książka (int Numpages); // Konstruktor 

Jest wywoływany z linii

 Książka ABook (128); 

Tworzy to obiekt o nazwie ABook typu Book i wywołuje funkcję Book () za pomocą parametr 128.

03

z 09

Więcej o klasie książek

W C ++ konstruktor zawsze ma taką samą nazwę jak klasa. Konstruktor jest wywoływany podczas tworzenia obiektu i tam należy umieścić kod w celu zainicjowania obiektu.

W książce Następny wiersz po konstruktorze destruktor. To ma taką samą nazwę jak konstruktor, ale przed nim ~ (tylda). Podczas niszczenia obiektu wywoływany jest destruktor w celu uporządkowania obiektu i zapewnienia zwolnienia zasobów, takich jak pamięć i uchwyt pliku używany przez obiekt.

Zapamiętaj- klasa xyz ma funkcję konstruktora xyz () i funkcję destruktora ~ xyz (). Nawet jeśli nie zadeklarujesz, kompilator po cichu je doda.

Destruktor jest zawsze wywoływany, gdy obiekt zostanie zakończony. W tym przykładzie obiekt jest domyślnie niszczony, gdy wykracza poza zakres. Aby to zobaczyć, zmodyfikuj deklarację destruktora na:

 ~ Book () {std:: cout << „Destructor called”;}; // Niszczyciel 

Jest to funkcja wbudowana z kodem w deklaracji. Innym sposobem na wstawienie jest dodanie słowa w wierszu

 inline ~ Book (); // Niszczyciel


i dodaj destruktor jako funkcję taką jak ta.

 Inline Book:: ~ Book (void) { 

 std:: cout << „Nazwany Destructor”;

 }


Funkcje wbudowane są wskazówkami dla kompilatora, aby wygenerować bardziej wydajny kod. Powinny być używane tylko do małych funkcji, ale jeśli są używane w odpowiednich miejscach - na przykład w środku pętle—Może mieć znaczącą różnicę w wydajności.

04

z 09

Pisanie metod klasowych

Najlepsze praktyki dla obiektów oznacza uczynienie wszystkich danych prywatnymi i dostęp do nich za pomocą funkcji znanych jako funkcje akcesora. SetPage () i GetCurrentPage () są dwie funkcje używane do uzyskania dostępu do zmiennej obiektowej Bieżąca strona.

Zmienić klasa deklaracja struktury i rekompilacji. Powinien nadal się kompilować i działać poprawnie. Teraz dwie zmienne Liczba stron i Bieżąca strona są publicznie dostępne. Dodaj ten wiersz za Book ABook (128), a on się skompiluje.

 Książka. PageCount = 9;


Jeśli zmienisz struct z powrotem na klasa i przekompiluj, ta nowa linia nie będzie się już kompilować jako Liczba stron jest teraz ponownie prywatny.

:: Notacja

Po treści deklaracji klasy książki znajdują się cztery definicje funkcji składowych. Każda z nich jest zdefiniowana z prefiksem Book:: w celu identyfikacji jej jako należącej do tej klasy.:: nazywa się identyfikatorem zasięgu. Identyfikuje funkcję jako część klasy. Jest to oczywiste w deklaracji klasy, ale nie poza nią.

Jeśli zadeklarowałeś funkcję członka w klasie, musisz podać jej treść w ten sposób. Jeśli chcesz, aby klasa Book była używana przez inne pliki, możesz przenieść deklarację książki do osobnego nagłówek plik, prawdopodobnie o nazwie book.h. Każdy inny plik może następnie dołączyć do niego

 #include „book.h” 

05

z 09

Dziedziczenie i polimorfizm

Ten przykład pokaże dziedziczenie. Jest to aplikacja dwuklasowa, z której jedna klasa pochodzi od innej.

 #zawierać 

 #zawierać 


 punkt klasy

 {


 int x, y;

 publiczny:

 Point (int atx, int aty); // Konstruktor

 inline virtual ~ Point (); // Niszczyciel

 virtual void Draw ();

 }; 


 Koło klasy: punkt publiczny {


 wewnętrzny promień;

 publiczny:

 Circle (int atx, int aty, int theRadius);

 inline virtual ~ Circle ();

 virtual void Draw ();

 };



 Point:: Point (int atx, int aty) {

 x = atx;

 y = aty;

 }


 inline Point:: ~ Point (void) { 

 std:: cout << „Nazwany Point Destructor”;

 }


 void Point:: Draw (void) {

 std:: cout << "Punkt:: Rysuj punkt na" << x << "" << y << std:: endl;

 }



 Circle:: Circle (int atx, int aty, int theRadius): Point (atx, aty) {

 promień = theRadius;

 }


 inline Circle:: ~ Circle () {

 std:: cout << „Niszczyciel okręgu o nazwie„ << std:: endl;

 }


 void Circle:: Draw (void) {

 Point:: Draw ();

 std:: cout << „okrąg:: Rysuj punkt” << „Promień” << promień << std:: endl;

 }


 int main () {

 Koło ACircle (10,10,5);

 Koło. Remis() ;

 zwraca 0;

 }


Przykład ma dwie klasy, Punkt i Okrąg, modelujące punkt i okrąg. Punkt ma współrzędne xiy. Klasa Circle pochodzi od klasy Point i dodaje promień. Obie klasy obejmują Remis() funkcja członka. Aby ten przykład był krótki, wynikiem jest po prostu tekst.

06

z 09

Dziedzictwo

Klasa okrąg pochodzi z Punkt klasa. Odbywa się to w tym wierszu:

 Koło klasy: Punkt {


Ponieważ wywodzi się z klasy bazowej (punkt), Circle dziedziczy wszystkich członków klasy.

 Point (int atx, int aty); // Konstruktor

 inline virtual ~ Point (); // Niszczyciel

 virtual void Draw ();


 Circle (int atx, int aty, int theRadius);

 inline virtual ~ Circle ();

 virtual void Draw ();


Pomyśl o klasie Circle jako klasie Point z dodatkowym członkiem (promieniem). Dziedziczy funkcje klasy podstawowej i zmienne prywatne x i y.

Nie może ich przypisywać ani używać, chyba że niejawnie, ponieważ są one prywatne, dlatego musi to zrobić za pomocą listy Inicjatora konstruktora Circle. To jest coś, co powinieneś zaakceptować na razie. Wrócę do list inicjalizacyjnych w przyszłym samouczku.

W Circle Constructor, wcześniej theRadius jest przypisany do promień, część Point Circle jest konstruowana poprzez wywołanie konstruktora Point na liście inicjalizacyjnej. Ta lista zawiera wszystko pomiędzy: a {poniżej.

 Circle:: Circle (int atx, int aty, int theRadius): Point (atx, aty) 


Nawiasem mówiąc, inicjalizacji typu konstruktora można używać dla wszystkich typów wbudowanych.

 int a1 (10);

 int a2 = 10;


Oba robią to samo.

07

z 09

Co to jest polimorfizm?

Polimorfizm to ogólny termin, który oznacza „wiele kształtów”. W C ++ najprostszą formą polimorfizmu jest przeciążenie funkcji. Na przykład wywoływano kilka funkcji SortArray (typ tablicy) gdzie może być sortarray szyk ints lub debel.

Interesuje nas tylko forma polimorfizmu OOP. Odbywa się to poprzez utworzenie funkcji (np. Draw ()) wirtualny w klasie bazowej Point, a następnie nadpisując go w Klasy pochodnej Okrąg.

Chociaż funkcja Remis() jest wirtualny w klasie pochodnej okrąg, to nie jest tak naprawdę potrzebne - to tylko przypomnienie, że to jest wirtualne. Jeśli funkcja w klasie pochodnej pasuje do funkcji wirtualnej w klasie podstawowej pod względem nazw i typów parametrów, jest ona automatycznie wirtualna.

Rysowanie punktu i rysowanie okręgu to dwie bardzo różne operacje ze wspólnymi tylko współrzędnymi punktu i okręgu, dlatego ważne jest, aby prawidłowe Remis() jest nazywany. Jak kompilatorowi uda się wygenerować kod, który uzyska odpowiednią funkcję wirtualną, zostanie omówiony w przyszłym samouczku.

08

z 09

Konstruktorzy C ++

Konstruktory

Konstruktor to funkcja, która inicjuje elementy obiektu. Konstruktor wie tylko, jak zbudować obiekt własnej klasy.

Konstruktory nie są automatycznie dziedziczone między klasami podstawową i pochodną. Jeśli nie podasz jednej w klasie pochodnej, zostanie dostarczona wartość domyślna, ale może to nie zrobić tego, co chcesz.

Jeśli nie podano konstruktora, kompilator tworzy domyślny bez żadnych parametrów. Zawsze musi istnieć konstruktor, nawet jeśli jest domyślny i pusty. Jeśli podasz konstruktorowi parametry, wówczas NIE zostanie utworzone ustawienie domyślne.

Kilka uwag na temat konstruktorów:

  • Konstruktory są funkcjami o tej samej nazwie co klasa.
  • Konstruktory mają na celu inicjowanie członków klasy podczas tworzenia instancji tej klasy.
  • Konstruktory nie są wywoływane bezpośrednio (z wyjątkiem list inicjalizacyjnych)
  • Konstruktory nigdy nie są wirtualne.
  • Można zdefiniować wiele konstruktorów dla tej samej klasy. Muszą mieć różne parametry, aby je rozróżnić.

Jest wiele więcej informacji na temat konstruktorów, na przykład konstruktorów domyślnych, konstruktorów przypisania i konstruktorów. Zostaną one omówione w następnej lekcji.

09

z 09

Porządkowanie niszczycieli C ++

Destruktor jest funkcją składową klasy, która ma taką samą nazwę jak konstruktor (i klasa), ale z ~ (tyldą) z przodu.

 ~ Koło ();


Gdy obiekt wykracza poza zakres lub rzadziej zostaje jawnie zniszczony, wywoływany jest jego destruktor. Na przykład, jeśli obiekt ma zmienne dynamiczne, takie jak wskaźniki, należy je zwolnić, a destruktor jest odpowiednim miejscem.

W przeciwieństwie do konstruktorów, destruktory mogą i powinny być wirtualne, jeśli wyprowadziłeś klasy. w Punkt i okrąg przykład klasy, destruktor nie jest potrzebny, ponieważ nie ma potrzeby czyszczenia (służy jedynie jako przykład). Czy byłyby dynamiczne zmienne składowe (jak wskaźniki), to wymagałyby one zwolnienia, aby zapobiec wyciekom pamięci.

Ponadto, gdy klasa pochodna dodaje elementy wymagające uporządkowania, potrzebne są wirtualne destruktory. W trybie wirtualnym najpierw wywoływany jest destruktor klasy najbardziej pochodnej, a następnie destruktor jego bezpośredniego przodka i tak dalej, aż do klasy podstawowej.

W naszym przykładzie

 ~ Koło ();

następnie

 ~ Point ();


Destruktor klas bazowych nazywany jest ostatnim.

To kończy tę lekcję. W następnej lekcji zapoznaj się z domyślnymi konstruktorami, konstruktorami kopiowania i przypisaniem.