NOVINKA! E-learningové kurzy umělé inteligence. Nyní AI za nejlepší ceny. Zjisti více:
NOVINKA – Víkendový online kurz Software tester, který tě posune dál. Zjisti, jak na to!

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.

Vytvoření projektu v C++ - Objektově orientované programování v C++

Projekt založíme jako klasický prázdný (Empty) C++ projekt. Následně klikneme na OK.

Vytvoření nového prázdného C++ projektu ve Visual Studio - Objektově orientované programování v C++

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.

Přidání souboru do projektu - Objektově orientované programování v C++

Následně vybereme .cpp soubor.

Typ souboru - Objektově orientované programování v C++

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.

Přidání třídy v C++ projektu - Objektově orientované programování v C++

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:

Nastavení vlastností třídě v C++ - Objektově orientované programování v C++

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 162x (4.66 kB)
Aplikace je včetně zdrojových kódů v jazyce C++

 

Předchozí článek
Úvod do objektově orientovaného programování v C++
Všechny články v sekci
Objektově orientované programování v C++
Přeskočit článek
(nedoporučujeme)
Řešené úlohy k 1. a 2. lekci OOP v C++
Článek pro vás napsal Patrik Valkovič
Avatar
Uživatelské hodnocení:
51 hlasů
Věnuji se programování v C++ a C#. Kromě toho také programuji v PHP (Nette) a JavaScriptu (NodeJS).
Aktivity