Fotografický magazín "iZIN IDIF" každý týden ve Vašem e-mailu.
Co nového ve světě fotografie!
Zadejte Vaši e-mailovou adresu:
Kamarád fotí rád?
Přihlas ho k odběru fotomagazínu!
Zadejte e-mailovou adresu kamaráda:
C/C++
Základy OOP v C++: Od C k C++
6. prosince 2000, 00.00 | první díl seriálu o objektově orientovaném programování v C++. Podobně jako v ostatních článcích se nejprve podíváme jaký je rozdíl mezi klasickým Céčkem a C++.
Úvodem musím říci, že můj seriál článků "Základy objektově orientovaného programováni v C++" je určen lidem, kteří znají jazyk C, a chtějí se naučit objektově programovat v jazyce C++. Pro ty, kteří jazyk C neznají, bych nejprve doporučil seriál článků mého kolegy pana Růžičky, který také vychází na serveru Builder.cz. Dále bych chtěl také upozornit, že veškerý můj výklad se bude týkat ANSI normy jazyka C++, a budu-li vycházet z jazyka C, budu vycházet jen z ANSI normy jazyka C. Je tak zaručen bezproblémový přenos zdrojových textů mezi překladači různých firem, a dokonce i mezi různými operačními systémy. Bohužel ANSI norma C++ narozdíl od ANSI C, je známa teprve 2 roky, a mnoho starších překladačů ji nedodržuje, i když to o sobě prohlašují. Já všechny příklady zdrojových textů, které zde budu prezentovat, budu zkoušet na překladačích Borland C++ Builder BETA 0.0.4.212, a GNU C/C++ Compiler. Druhý zmiňovaný je standardní překladač pod OS Linux, který by měl ANSI C++ dodržovat. První zmiňovaný je testovací verze Builderu (ani ne verze 1) fy Borland, která jej uvolnila pro otestování. Můžete jej získat volně na některém z CD časopisu Chip, které vyšlo v roce 1996, nebo 1997. Tento překladač je již poměrně starý, ale dosud jsem nenarazil na nic z ANSI normy co by nepodporoval. Narazím-li na něco v průběhu psaní tohoto seriálu článku, upozorním vás na to. Máte-li však novější verzi Borland C++ Builderu, je to dobře pro vás. Od fy Borland by měl prý vyhovovat i překladač Borland C/C++ 5. Starší už ale asi ne. O překladačích jiných firem bohužel nevím nic, proto si budete muset zjistit sami nakolik podporují ANSI normu.
Protože snad 99.9% všech knih, či článků začíná na úvod malým programem, který pozdraví svět, začnu takto i já. Protože čtenář, který teprve začíná s C++ asi nebude vědět co se děje, doporučuji tento program jen opsat bez přemýšlení. Vstupně výstupním operacím se chci věnovat až někdy kolem 10. článku. A nyní slibovaný program pozdrav.cpp:
#include <iostream.h>
void main(void)
{
cout << "Ahoj svete" << endl;
}
Tuto otázku si klade asi každý, kdo s C++ začíná. Odpověď není vůbec tak jednoduchá jak se zdá. Já bych odpověděl: "Až na několik málo vyjímek si ano". Obecně platí, že C++ je rozšíření jazyka C. Jazyk C je čistě strukturovaný programovací jazyk. V jazyce C++ lze programovat objektově, nebo také strukturovaně. Bohužel jazyk C++ umožňuje i jakýsi mix strukturovaného, a objektově orientovaného programování. Tento mix vám rozhodně nedoporučuji. Zbytek tohoto článku budu věnovat strukturovanému programování v C++, a počínaje příštím článkem se budu věnovat jen objektově orientovanému programování.
Zde popíšu v čem není C s C++ kompatibilní. Je to těch několik málo vyjímek, o kterých jsem se zmínil v minulém odstavci. Není totiž každý program napsaný pro C kompilovatelný jako program napsaný v C++.
MojeFunkce(int cislo);
v jazyce C je funkce, která vrací int, kdežto v C++ se jedná o deklaraci funkce vracející void.
Možná, že těchto drobných problémů bude více. Já jsem však přišel jen na tyto. Jinak lze program napsaný v jazyce C považovat za program v jazyce C++. Pro strukturované programování však C++ nabízí řadu příjemných rozšíření.
Protože se v tomto seriálu článků chci zabývat objektově orientovaným programováním, popíšu jen letmo ty rozšíření, které se mi zdají opravdu nejvýznamnější.
int PocetCtvercu; // Udává počet čtverců
bool a;
bool b = true;
int c = 20;
bool d = ((c == 20) || ( c<=5));
a = !b;
if (a)
{
. . .
}
int soucet(int a, int b, int c = 0) /* 3. parametr je implicitně 0. */
{
return (a+b+c); /* vracím součet parametrů*/
}
void main(void)
{
int cislo;
. . . // Nějaký program
cislo = soucet(1,2,3); /* Zavolá se funkce soucet s parametry a = 1 , b = 2, c = 3 - To asi nikoho nepřekvapí.*/
. . . // Nějaký program
cislo = soucet(2,3); /* Zavolá se funkce soucet s parametry a = 2 , b = 3, c = 0. Tedy je to stejný výsledek, jako bych napsal cislo = soucet(2,3,0). */
}
Implicitní hodnoty parametrů mohu zadávat jen v seznamu parametrů zprava. Pokud by tedy v naší funkci součet nemel parametr c implicitní hodnotu, parametr b by ji také nemohl mít. Parametr c (1. zprava) implicitní hodnotu má, proto lze definovat i implicitní hodnotu parametru b (2. zprava).
int max(int a, int b)
{
return (a>b)? a:b;
}
float max(float a, float b)
{
return (a>b)? a:b;
}
Zavolám-li funkci max s parametry typu float vrátí mi větší z nich jako typ float. Zavolám-li funkci max s parametry typu int vrátí mi větší z nich jako typ int. Název funkce max jsem přetížil. Při přetěžování funkcí musíte dávat pozor na případné nejednoznačnosti. Kdyby jste v našem příkladě zavolali funkci max(1.0,2.0), překladač by vás upozornil na chybu. Neví totiž, zda volat max s parametry float, nebo parametry implicitně přetypovat na int a volat max s parametry int. Tedy volání funkce je nejednoznačné, překladač neví, kterou funkci vybrat. Tento problém vyřešíte, jestliže budete volat max((float)2.0,(float)3.5). Nejlepší způsob jak předcházet případným nejednoznačnostem je nepřetěžovat funkce tak, aby mezi parametry šlo provést implicitní přetypování.
int a; // Proměnná typu int
int &b = a; /* Reference na proměnnou a, b je nyní jiný název pro číslo, které reprezentuje proměnná a, b je přezdívka a (alias). */
a++; /* Nyní jsem změnil hodnotu a, i hodnotu b. Změnil jsem vlastně jen jednu hodnotu, proměnná a i b reprezentují tutéž proměnnou. */
Jedná se vlastně o jakousi obdobu klasického ukazatele (pointeru) v jazyce C. Ale POZOR reference NENÍ ukazatel. Narozdíl od ukazatele nemůže ukazovat "nikam", tedy mít hodnotu NULL. Právě tento fakt je důvod, proč já osobně reference nepoužívám, ale používám "staré a dobré" pointery - ostatně jak uvidíte v následujících článcích. I když jsem někde četl, že právě tato vlastnost je výhodou referencí od ukazatelů, mně se naopak zdá, že je nevýhodou. U reference totiž musím již v době deklarace znát proměnnou, kterou bude zastupovat, což u ukazatele nemusím. Chci-li někde nějakým způsobem použít sdílení proměnných, použiji raději ukazatele. Reference má výhodu oproti ukazatelům snad jen při předávání parametrů funkcí odkazem. Například funkci swap, která vymění hodnotu dvou čísel, je zbytečné psát pomocí ukazatelů, když v C++ lze zapsat následovně:
swap(int &a, int &b)
{
int c = a;
a = b;
b = c;
}
// A někde v programu ji volat takto:
int a = 2, b = 9;
swap(a,b);
Tento zápis je přece jenom čitelnější a "lehčí" než implementace stejné funkce v jazyce C.
Závěrem bych chtěl jen dodat, že rozšíření jazyka C++ oproti C pro strukturované programování je jistě mnohem více. Tento článek byl jen orientační, a hlavně odbočení od tématu seriálu o objektově orientovaném programování v C++. Zdálo se mi jen vhodné se o možnosti strukturovaného programování v jazyce C++ zmínit. Příště se chci podívat na základní pojmy objektově orientovaného programování. Vysvětlím v něm pojmy OOP jako jsou objekt, třída objektů, zpráva atd... A poté v dalších článcích chci ukázat, jak objektově programovat v jazyce C++.
Obsah seriálu (více o seriálu):
- Základy OOP v C++: Od C k C++
- Základní pojmy objektově orientovaného programování
- Vytváření tříd, instance třídy, zasílání zpráv v C++
- Vytváření instancí - konstruktory, destruktory
- Kopírovací konstruktor v C++
- Jednoduchá dědičnost v C++
- Časná versus pozdní vazba - úvod do polymorfismu v C++
- Polymorfismus - dokončení
- Vícenásobná dědičnost v C++
- Vícenásobná dědičnost v C++ - opakovaná dědičnost
- Vícenásobná dědičnost v C++ - volání konstruktorů a destruktorů
- Přetěžování operátorů v C++ 1.díl
- Přetěžování operátorů v C++ 2. díl
- Vstupní a výstupní operace pomocí datových proudů v C++
- Přetěžování operátorů << a >> pro datové proudy v C++
- Neformátovaný vstup a výstup v C++
- Paměťové proudy v C++
- Prostory jmen v C++
- Řetězce v C++
- Výjimky v C++
- Výjimky v C++ - výjimky tvoří dědičnou hierarchii
- Výjimky v C++ - dokončení
- Dynamická identifikace typů v C++
- Přetypování v C++
- Problémy s typy při vícenásobné dědičnosti
- Šablony funkcí v C++
- Šablony datových typů v C++
- Vnitřní typy u parametrů šablon, vnořené šablony v C++
- Pole s libovolným intervalem indexování v C++
- Datové kontejnery v C++ - Úvod do STL
- Vector - datový kontejner v C++
- Iterátory v C++
- Šablona vector v C++ a iterátory
- Asociativní pole v C++
- Množina v C++
- Funkční objekty v C++
- Standardní funkční objekty v C++
- Úvod do standardních algoritmů v C++
- Kopírovací a přesouvací algoritmy v C++
- Vyhledávací algoritmy v C++
- Skenovací (prohlížecí) algoritmy v C++
- Transformační algoritmy v C++
- Řadící algoritmy v C++
- Halda v C++
- Standardní algoritmy v C++ - dokončení
- Automatické ukazatele v C++
- Inteligentní ukazatel - čítač referencí v C++
- Použití čítače referencí v C++
- Kopírování velkých objektů v C++
- Řízené kopírování prvků v poli v C++
- Dokončení seriálu objektově orientované programování v C++
-
25. listopadu 2012
-
30. srpna 2002
-
10. října 2002
-
4. listopadu 2002
-
12. září 2002
-
25. listopadu 2012
-
28. července 1998
-
31. července 1998
-
28. srpna 1998
-
6. prosince 2000
-
27. prosince 2007
-
4. května 2007