Lekce 2 - První objektová aplikace v C++
V lekci Úvod do objektově orientovaného programování v C++ jsme si prošli úvodem do objektově orientovaného programování, vysvětlili si okolnosti vzniku OOP a také pojem třída.
Na začátku kurzu se základními strukturami jazyka C++ jsme si vytvořili program Hello world. Udělejme si nyní podobný program jako úvod do objektově orientovaného programování. Naprogramujme si Hello object world!
Vytvoření projektu
Nejprve si vytvoříme nový projekt. Postup vytvoření projektu můžete vidět na screenshotech níže.
Projekt založíme jako klasický prázdný (Empty) C++ projekt. Následně klikneme na OK.
V projektu si vytvoříme nový soubor main.cpp, což uděláme kliknutím pravým tlačítkem na projekt v Solution Exploreru -> Add -> New Item.
Následně vybereme .cpp soubor.
Do tohoto souboru vložíme základní strukturu aplikace v C++ jako jsme byli zvyklí doposud:
#include <iostream> using namespace std; int main() { return 0; }
V Solution Exploreru klikneme pravým tlačítkem myši na složku Source files a vybereme Add -> Class.
V okně, které se nám zobrazí, rozklikneme C++ Class. Pak se zobrazí další okno, ve kterém vyplníme údaje podle obrázku. Jde o zadání názvu souborů třídy, která bude reprezentovat vzor pro objekt, který umí pozdravit:
Visual studio nám vytvoří dva soubory: Zdravic.h (tam bude samotná třída) a Zdravic.cpp (kde budou definice funkcí). Rozdělení třídy do těchto dvou souborů je nutné - viz lekce o kompilaci v C a C++. Obsah souborů přepíšeme do následující podoby:
Zdravic.h
#ifndef __ZDRAVIC_H__ #define __ZDRAVIC_H__ class Zdravic { }; #endif
Zdravic.cpp
#include "Zdravic.h"
Preprocesové direktivy (#ifndef
, #define
a
#endif
) zajišťují, že bude soubor includován jen jednou.
Visual Studio ve výchozím nastavení používá #pragma once
direktivu, ale námi ukázaná je praktičtější (funguje i při kompilaci na
Linuxech). Původně vygenerované funkce Zdravic(void)
a
~Zdravic(void)
byly tzv. konstruktor a destruktor, na které se
podíváme až v příští lekci.
Deklarace metody
Až budeme tuto třídu používat, budeme chtít, aby něco uměla. Kvůli tomu si třídu Zdravic rozšíříme o nějakou metodu. Ta se v C++ zapisuje stejně jako funkce:
Zdravic.h
#ifndef __ZDRAVIC_H__ #define __ZDRAVIC_H__ class Zdravic { public: void pozdrav(); }; #endif
Zdravic.cpp
#include <iostream> #include "Zdravic.h" using namespace std; void Zdravic::pozdrav(void) { cout << "Hello object world!"; }
Metodu musíme deklarovat 2x, jednou jako hlavičku do .h souboru a jednou i s tělem do .cpp souboru. Zde jsme prozatím skončili, přejdeme do main.cpp.
Vytvoření instance třídy
Nyní si v těle metody main()
vytvoříme instanci třídy
Zdravic. Nejdříve ale musíme říct, že chceme používat naši třídu
Zdravic
, kterou jsme si před chvílí vytvořili. To provedeme
naincludováním naší třídy do souboru main.cpp
pomocí
#include "Zdravic.h"
. Na rozdíl od klasických includů
(například iostream) si můžete všimnout nahrazení ostrých
závorek za uvozovky. Pokud použijeme hranaté závorky, kompilátor hledá
soubor ve svých cestách (zpravidla cesty ke knihovnám). Pokud použijeme
uvozovky, kompilátor použije relativní cestu (v našem případě aktuální
projekt).
Objekty se ukládají do proměnných, název třídy slouží jako datový
typ (jak je tomu například u int), instance můžeme pojmenovat jakkoliv.
Deklarujme si proměnnou a následně v ní založme novou instanci třídy
Zdravic
:
#include <iostream> #include "Zdravic.h" using namespace std; int main() { Zdravic _zdravic; return 0; }
Tím se vytvoří proměnná _zdravic
. Instanci můžeme
vytvořit i takto:
Zdravic* _zdravic = new Zdravic();
Tento způsob vytvoří instanci dynamicky na haldě. Vrátíme se k němu v pokročilejších dílech našeho C++ kurzu.
Volání metody
A protože již máme vytvořený svůj první objekt (instanci), můžeme
zavolat jeho metodu. Na konec kódu (před return 0;
) ještě
doplníme cin.get()
(aby program hned neskončil a čekal na stisk
libovolné klávesy). Soubor main.cpp vypadá ve finále takto:
main.cpp
#include <iostream> #include "Zdravic.h" using namespace std; int main() { Zdravic _zdravic; _zdravic.pozdrav(); cin.get(); return 0; }
Teď můžeme program spustit. Výstup bude následující:
Konzolová aplikace
Hello object world!
Máme tedy svou první objektovou aplikaci! Logiku provádí příslušný objekt. Až budeme psát větší aplikace, rozdělení funkcí do jednotlivých objektů velmi oceníme kvůli přehlednosti.
Parametry metody
Dejme nyní naší metodě pozdrav()
parametr jmeno,
aby dokázala pozdravit konkrétního uživatele:
Zdravic.h
#ifndef __ZDRAVIC_H__ #define __ZDRAVIC_H__ #include <string> using namespace std; class Zdravic { public: void pozdrav(string jmeno); }; #endif
Zdravic.cpp
#include <iostream> #include "Zdravic.h" using namespace std; void Zdravic::pozdrav(string jmeno) { cout << "Ahoj uzivateli " << jmeno << endl; }
Nyní upravíme naši funkci main()
:
Zdravic _zdravic; _zdravic.pozdrav("Karel"); _zdravic.pozdrav("Petr");
A po spuštění aplikace získáme následující výstup:
Konzolová aplikace
Ahoj uzivateli Karel
Ahoj uzivateli Petr
Atributy třídy
Třídě nyní přidáme nějaká data ("proměnnou"), kde bude uložen text pozdravu. Z minulé lekce již víme, že třídy obsahují funkcionalitu a data. Funkci již máme, ukažme si tedy jak se do objektů ukládají data. Datové složky třídy (atributy) se definují stejně jako proměnné. Upravme tedy naši třídu:
Zdravic.h
Atribut (proměnnou) deklarujeme v hlavičkovém souboru:
class Zdravic { public: string text; void pozdrav(string jmeno); };
Nyní si všechny instance třídy Zdravic ukládají svůj text.
Zdravic.cpp
Upravme metodu pozdrav()
tak, aby ke zdravení používala text
v atributu text
:
void Zdravic::pozdrav(string jmeno) { cout << text << " " << jmeno << endl; }
main.cpp
Text nyní musíme prvně nastavit vytvořené instanci v main.cpp:
Zdravic _zdravic; _zdravic.text = "Ahoj uzivateli"; _zdravic.pozdrav("Karel"); _zdravic.pozdrav("Petr"); _zdravic.text = "Vitam te tu programatore"; _zdravic.pozdrav("Richard");
A výstup aplikace:
Konzolová aplikace
Ahoj uzivateli Karel
Ahoj uzivateli Petr
Vitam te tu programatore Richard
Návratová hodnota metody
Vzhledem k objektovému návrhu není nejvhodnější, aby každý objekt
ovlivňoval vstup a výstup. Pochopitelně narážím na naše vypisování do
konzole. Každý objekt by měl mít určitou kompetenci (odpovědnost) a tu by
neměl překračovat. Pověřme náš objekt pouze sestavením pozdravu a jeho
výpis si zpracujeme někde jinde, v našem případě v metodě
main()
. Výhodou takto navrženého objektu je vysoká
univerzálnost a znovupoužitelnost. Objekt doposud umí jen psát do konzole,
my ho však přizpůsobíme tak, aby daná metoda text pouze vracela a bylo na
jeho příjemci, jak s ním naloží. Takto můžeme pozdravy ukládat do
souborů, vypsat na formulář nebo dále zpracovávat.
Jelikož chceme, aby metoda vracela hodnotu typu string
,
změníme její dosavadní typ void
na string
. K
návratu hodnoty použijeme příkaz return
. Upravme kód
třídy:
Zdravic.h
class Zdravic { public: string text; string pozdrav(string jmeno); };
Zdravic.cpp
A stejně tak i implementaci:
string Zdravic::pozdrav(string jmeno) { return text + " " + jmeno + "!\n"; }
main.cpp
K tomu musíme upravit soubor main.cpp:
int main() { Zdravic _zdravic; _zdravic.text = "Ahoj uzivateli"; cout << _zdravic.pozdrav("Karel"); cout << _zdravic.pozdrav("Petr"); _zdravic.text = "Vitam te tu programatore"; cout << _zdravic.pozdrav("Richard"); cin.get(); return 0; }
Nyní je náš kód dle dobrých praktik. Zdrojové kódy jsou přiloženy pod článkem. Celý program si můžete vyzkoušet zde nebo v přiloženém projektu.
#include <iostream> #include "zdravic.h" using namespace std; int main() { zdravic _zdravic; _zdravic.text = "Ahoj uzivateli"; cout << _zdravic.pozdrav("Karel"); cout << _zdravic.pozdrav("Petr"); _zdravic.text = "Vitam te tu programatore"; cout << _zdravic.pozdrav("Richard"); cin.get(); return 0; }
#include <iostream> #include "zdravic.h" using namespace std; string zdravic::pozdrav(string jmeno) { return text + " " + jmeno + "!\n"; }
#ifndef __ZDRAVIC_H__ #define __ZDRAVIC_H__ #include <string> using namespace std; class zdravic { public: string text; string pozdrav(string jmeno); }; #endif
A jsme u konce. Námi napsaný program má již nějakou úroveň, i když vlastně nic nedělá. Za úkol máte předělat si naši konzolovou kalkulačku do objektů.
V následujícím cvičení, Řešené úlohy k 1. a 2. lekci OOP v C++, si procvičíme nabyté zkušenosti z předchozích lekcí.
Měl jsi s čímkoli problém? Stáhni si vzorovou aplikaci níže a porovnej ji se svým projektem, chybu tak snadno najdeš.
Stáhnout
Stažením následujícího souboru souhlasíš s licenčními podmínkami
Staženo 160x (4.66 kB)
Aplikace je včetně zdrojových kódů v jazyce C++