Programujeme v C++ (1) - Úvod

22.06.2008 19:35 | Články | Miroslav Bendík
Tento seriál bude venovaný základom programovania v C++. Cieľom tohto seriálu je poskytnúť základy objektovo orientovaného programovania v C++.

Od tohto seriálu v žiadnom prípade nečakajte podrobný popis vlastností jazyka C++. Seriál je zameraný predovšetkým na programovanie pod linuxom preto budem v tomto seriáli uvádzať príklady prispôsobené pre tento OS. Okrem samotného C++ okrajovo spomeniem nástroje na automatickú kompiláciu rozsiahlejších projektov ako je make a cmake.

O C++

Jazyk C++ patrí medzi vyššie programovacie jazyky. Je vhodný na systémové programovanie rovnako ako aj na programovanie aplikácii. Štandard C++ je veľmi rozsiahly a nie je v mojich možnostiach popísať všetky vlastnosti jazyka C++.

C++ ako už názov napovedá bol vyvinutý ako rozšírenie jazyka C. Syntakticky sú si C a C++ veľmi podobné preto je možné mnoho programov napísaných v C skompilovať pomocou C++ kompilátora.

Ahoj svet!

Prvý program ktorý si v tomto seriáli ukážeme bude slovenská verzia programu Hello world.

#include <cstdio>

using namespace std;
int main(int argc, char *argv[])
{
    printf("Ahoj svet!\n");
    return 0;
}

Tento program používa hlavičkový súbor z ISO C. Všetky hlavičkové súbory z ISO C majú v C++ ekvivalent pomenovaný c(názov súboru v ISO C bez prípony). Takže ak chceme používať funkcie z stdio.h stačí použiť #include <cstdio>.

Hlavný program je rovnako ako v C main s návratovou hodnotou typu integer a parametrami argc a char *argv[]. Na návratovú hodnotu by sme ako správní programátori nemali zabúdať. Akákoľvek iná hodnota ako 0 je považovaná za chybový kód. Ak zabudneme na return bude aplikácia vracať náhodnú hodnotu čo môže byť vyhodnotené ako chyba. Funkcia printf() vypíše na štandardný výstup formátovaný reťazec.

Kompilácia

Pri kompilácii C++ programu si na Linuxe vystačíme s kompilátorom g++ a štandardnou knižnicou. Zdrojový kód vložíme do textového súboru s príponou cpp (je možné používať aj iné prípony, ale väčšina projektov používa príponu cpp). Posledný riadok súboru by mal byť prázdny inak bude kompilátor hlásiť varovanie. Program skompilujeme príkazom g++ -Wall program.cpp -o program. Voľba -Wall služi na to aby nám kompilátor vypisoval všetky varovania. Pre spustenie stačí príkaz ./program. Výstup programu by mal byť nasledujúci:

Ahoj svet!

Tento program je možné napísať aj alternatívnym spôsobom - pomocou streamov.

#include <iostream>

using namespace std;
int main(int argc, char *argv[])
{
    cout<<"Ahoj svet!"<<endl;
    return 0;
}

K streamom sa vrátime v niektorej z budúcich častí.

Programy skladajúce sa z niekoľkých súborov

Pri práci na väčších projektoch si nevystačíme s jediným súborom. Kompilátor g++ umožňuje kompiláciu niekoľkých zdrojových kódov samostatne a následné zlinkovanie do spustiteľného súboru. Pri kompilácii každej oddelenej časti programu musí kompilátor poznať deklarácie všetkých funkcií a premenných použitých v danej časti.

Deklarácia

Deklaráciou oznamujeme kompilátoru meno premennej alebo funkcie. Pri funkcii musí kompilátor poznať okrem mena funkcie aj návratovú hodnotu a počet a typ parametrov. V definícii funkcie je na rozdiel od deklarácie už aj samotný kód funkcie.

// deklaracia funkcie
int max(int x, int);

Ak by sme v žiadnej časti programu nedefinovali túto funkciu linker by nezlinkoval program pretože by nenašiel definíciu. Definícia funkcie v programe sa musí vyskytovať práve 1 krát pretože pri viacerých definíciách by linker nevedel zistiť ktorá definícia sa má použiť.

// definicia funkcie
int max(int a, int b)
{
    if (a > b)
        return a;
    else
        return b;
}

Pri definícii funkcie je potrebné uviesť aj telo funkcie. Deklarácia a definícia funkcie môžu mať rôzne názvy parametrov prípadne je možné názvy parametrov úplne vynechať. V tele funkcie platia tie parametre ktoré sú uvedené v definícii.

void ahoj()
{
    printf("Ahoj\n");
}

Toto je príklad deklarácie a zároveň definície funkcie. Ak sa identifikátor funkcie vyskytne 1. krát v programe pri definícii stáva sa definícia zároveň deklaráciou.

// definicie premennych
int a;
int b = 3;
// deklaracia premennej
extern int c;

Ak chceme napísať iba deklaráciu premennej musíme použiť kľúčové slovo extern. Aj keď premennej nepriradíme žiadnu hodnotu je bez použitia extern automaticky pri definícii deklarovaná.

Ahoj svet rozdelený na menšie časti

Ako príklad na oddelenú kompiláciu som použil starý známy program - ahoj svet. Náš projekt bude pozostávať z 3 súborov:

hello_main.cpp
hlavný program
hello_lib.cpp
definícia funkcie hello
hello_lib.h
deklarácia funkcie hello

Súbor hello_main.cpp bude vyzerať nasledovne:

#include "hello_lib.h"

int main(int argc, char *argv[])
{
    hello();
    return 0;
}

Systémové hlavičkové súbory sa včleňujú pomocou #include <…>. Vlastné hlavičkové súbory píšeme v úvodzovkách preto máme v programe #include "hello_lib.h". V hlavnom programe voláme funkciu hello definovanú v súbore hello_lib.cpp.

Súbor hello_lib.h bude obsahovať deklaráciu funkcie hello:

#ifndef HELLO_LIB_H
#define HELLO_LIB_H

void hello();

#endif

Okrem deklarácií sa do hlavičkových súborov vkladá kód pre preprocesor ktorý zabráni niekoľkonásobnému včleneniu toho istého súboru. Najčastejšie sa to dosahuje pridaním kódu:

#ifndef NÁZOV_SÚBORU_H
#define NÁZOV_SÚBORU_H

deklarácie

#endif

Je možné používať akýkoľvek text na zamedzenie niekoľkonásobného včlenenia, len musíme zaistiť aby tento text bol pre každý súbor iný. Najľahším spôsobom ako to zaistiť je použiť samotný názov súboru.

Nakoniec už len stačí definovať funkciu hello. To urobíme v súbore hello_lib.cpp.

#include "hello_lib.h"

#include <cstdio>

using namespace std;
void hello()
{
    printf("Ahoj svet!\n");
}

Takže program by sme mali, už stačí len skompilovať. Pre kompiláciu spustíme v adresári s projektom nasledujúce príkazy:

g++ -Wall hello_main.cpp -c -o hello_main.o
g++ -Wall hello_lib.cpp -c -o hello_lib.o
g++ hello_lib.o hello_main.o -o hello

Program spustíme pomocou ./hello.

V nasledujúcej časti si ukážeme ako sa dá využiť cmake pri kompilácii väčších projektov.

    • return 0 23.06.2008 | 02:39
      Avatar Samuel BWPOW Kupka Almalinux, OpenWRT  Používateľ
      Iba taka poznamka, ze (aspon programy kompilovane g++) vracaju vzdy hodnotu 0, ak ju priamo v programe neurcime (a nespadnu). A ani -Wall sa na to nestazuje.
      Strach dát najevo své pocity a zjednat si u druhých respekt je jedním z problémů civilizovaného člověka, který se naučil zpochybňovat svou vlastní pravdu pro zdání objektivity
    • Len tak ďalej 24.06.2008 | 01:43
      iyo   Návštevník
      Autorovi gratulujem, schopne napísaná časť... a nejakou zhodou náhod som sa stal cieľovou skupinou článku (do Cčka som už zabrdol, ale nie moc...) :-D

      Teším sa na ďalšiu časť, dúfam, že vyjde...
      • Re: Len tak ďalej 26.06.2008 | 22:06
        Avatar Tomi Windows XP Pro/Ubuntu  Používateľ
        jop, paci sa mi, ze autor nezacal rozoberat, co je to if, atd. ale ze predpoklada zakladne znalosti a pusta sa do zaujimavejsich a prakticnejsich veci :)

        mimochodom este nasiel som nieco pre tych, ktori sa nechcu ucit cmake, ale stare dobre make maju radsej ;) http://www.freshsourcing.sk/sk/content/50/
        Nobody is perfect. I am Nobody.
        • Re: Len tak ďalej 27.06.2008 | 10:58
          Avatar Miroslav Bendík Gentoo  Administrátor
          Budem písať aj o make aj o cmake. V ďalších častiach bude takmer nevyhnutnosť niečo také používať (teda ak sa mi bude chcieť toľko písať ...).
          • Re: Len tak ďalej 27.06.2008 | 13:25
            Avatar Tomi Windows XP Pro/Ubuntu  Používateľ
            ahoj,
            no mozno je to tazko splnitelny ciel, ale podla mna by bolo dobre tu rozoberat C++ na takej urovni, aby som ked si pozriem hocaky open source projekt, tak vedel si citat jeho zdrojaky a rozumel celej pouzitej syntaxi ;)

            totiz z vlastnej skusenosti viem, ze naucit sa zaklady programovania(napr. v Pythone- trvalo to asi 3 mesiace) a vediet sa bez obav pripojit niekde(dokym som sa dostal do toho stadia presli dalsie vyse 3 mesiace) su 2 rozne veci ;)

            a ako vidim, tak ty predpokladas znalost aspon nejakeho vyssieho jazyka, a zrejme budes predpokladat take zaklady, ako je znalost STLka a aspon znalost principov OOP ;-)

            tak s vervou do dalsieho pisania!
            Nobody is perfect. I am Nobody.
    • otazka na autora 26.06.2008 | 23:23
      Avatar m4jkl   Používateľ
      velmi by som uvital nieco o debugovani pod linuxom :) nechysta sa take nieco do niektorej dalsej casti serialu?
      • Re: otazka na autora 27.06.2008 | 11:00
        Avatar Miroslav Bendík Gentoo  Administrátor
        Hmm, debugovanie som neplánoval, ale keď tak rozmýšľam mohol by som pár riadkov napísať o gdb prípadne valgrind (na odhaľovanie únikov pamäte a profilovanie).
      • Re: otazka na autora 18.08.2008 | 20:01
        Avatar Gabriel Ševeček ml. Archlinux  Používateľ
        dobry tutorial k debugovaniu pod linuxom pomocou gdb je tu
        na bh nedavno vysla prva cast prekladu
    • vdaka 29.06.2008 | 15:40
      Avatar Murkobazko Fedora 12  Používateľ
      Vdaka za prvu cast tutorialu...osobne mi to velmi pomohlo. Tesim sa na dalsie casti...

      Nech sa dari
      "It's More Fun To Compute" - Kraftwerk
      • -..- 30.06.2008 | 19:23
        L_D   Návštevník
        Mirec mirec nachvilu nesi v skole a uz ucis ty ostatnych :) ale pohoda
    • std 04.07.2008 | 03:22
      Jaroslav Šmíd   Návštevník
      Musím si neodpustit takovou maličkost. Pokud includujete např. cstdlib, pak printf má být std::printf. Pokud iostream tak count má být std::count. Vy jste totiž neuvedl "using namespace std". Normální kompilátor by ve vašem případě měl zahlásit chybu či alespoň warning.
      • Re: std 04.07.2008 | 09:44
        Avatar Miroslav Bendík Gentoo  Administrátor
        Kompilátor mi síce varovanie nehlásil, ale s using namespace máte pravdu, už som to opravil.
    • ... 07.07.2008 | 02:11
      Avatar nardew debian  Používateľ
      oprav si typ formalneho parametra v main()
    • mensia kritika 01.02.2009 | 19:25
      ujo jozef   Návštevník
      1. Raz pouzivas IO C potom c++. Pises serial o C++ tak pouzivaj len IO C++.

      2. Preco pouzivas stare hlavickove subory ako cstdio? iostream nist?

      Systémové hlavičkové súbory sa včleňujú pomocou #include <…>. Vlastné hlavičkové súbory píšeme v úvodzovkách preto máme v programe #include "hello_lib.h"

      v < > su subory ktore ma hladat na standardnej ceste vacsinou /usr/src/include (da sa zmenit parametrom kompilatora). " " oznacuju ze sa hlavickovy subor nachadza v aktualnej zlozke.

      Inak v pohode idem citat dalsie diely:)