Napřed by bylo dobré říct, že funkce jsou prakticky úseky programů,
které se často opakují. Třeba pro výpočet sinusu by mohla být funkce,
nebo pro výpis chybové hlášky, prostě cokoli co se v programu opakuje
dáme do funkcí. Funkce může mít svoje jméno (jako proměnná, platí
i stejná pravidla). Potom když chceme funkci provést, říká se, že ji
voláme. Funkce potom může mít nějaké parametry - třeba sinus má jako
parametr double číslo. A taky může mít návratovou hodnotu. Třeba
ten sinus. (ale taky mít nemusí, stejně jako nemusí mít parametry)
Funkce se v C/C++ definují podobně, jako v paskalu ...
Funkce má v C-čku jméno, parametry a návratovou hodnotu.
Pokud nemá návratovou hodnotu, je to procedura, ale v C-čku
procedury nejsou, používá se speciální datový typ void, ten
se používá také, když funkce nemá parametry.
navratova_hodnota jmeno_funkce(parametry)
{
return hodnota_navratu;
}
|
Pokud funkce nemá parametry, může se použít void (ale nemusí), jen
ty závorky tam musí zůstat.
Teď ještě ten příkaz return - pomocí něj vrací funkce nějakou
hodnotu. Pokud je to procedura, dá se použít return pro vyskočení.
Například :
int Funkce_Pricti_Jedna(int i)
{
i ++;
return i;
}
|
Pokud funkci zavoláte :
int i;
i = Funkce_Pricti_Jedna(2);
|
V proměnné i bude hodnota 3.
void Procedura(int zpomaleni)
{
int i;
for(i = 0; i < zpomaleni; i ++)
;
// Toto je "prázdná" smyčka (prostě
// zabere trochu času jejím vykonáváním)
}
|
Tak tato procedura se bude volat :
A ještě jeden příklad :
float Pi_konstanta(void)
{
return 3.1415926;
}
|
Se bude volat :
p = Pi_konstanta(); // Ty závorky tam musí být, nesmí tu být void
|
A nebo funkce, volající sama sebe - tzv. rekurzivní :
int Mocnina(int zaklad, int kolik)
{
if(kolik < 1)
return 1;
return zaklad * Mocnina(zaklad, kolik - 1);
}
|
Tato funkce volá sama sebe a vypočítá mocninu čísla.
Také např. známé
.. je funkce. Je tu ještě jedna věc, kterou byste měli vědět. Aby funkce
mohla být volána z prostoru před ní(hned vysvětlím), musí mít funkční
prototyp. Ten se tvoří odtrhnutím prvního řádku funkce (až k '{' a
přidáním středníku na konec. Teď vysvětlení a příklad ...
int prvni(void)
{ ... } // Při volání jakékoli funkce nastane chyba
int main(void)
{ ... } // Při volání funkce druha() nastane chyba
int druha(void)
{ ... } // Funkce druha je bez omezení
|
Prostě jména funkcí a proměnných se zpracovávají postupně, jak překladač čte
zdrojový soubor, postupně si "zapamatovává" jména, takže když ve funkci prvni
napíšete Druha() tak nebude vědět "o co jde" a zahlásí chybu. To by bylo
vysvětlení, a nyní příklad. Pro :
Je funkční prototyp :
A pro :
void Pocitej(float a, int b, double c)
{ ... };
|
Je funkční prototyp :
void Pocitej(float, int, double);
|
Nebo (doporučená a lepší verze) :
void Pocitej(float a, int b, double c);
// Tato alternativa je lepší
|
A teď otázka otázek : "Kam s ním ?" Odpověď je jednoduchá :
Do souboru.h, a nebo na začátek souboru. Proč do .h ? to proto,
že vytvoříte samostatný modul, který se dá dál použít.
Uvedu příklad prototypu na začátku souboru :
/* Soubor .cpp */
#include <stdio.h>
void tiskni(int i);
// Toto je funkční prototyp
// funkce tiskni.
int main(void)
{
int i;
for(i = 0; i < 10; i++)
tiskni(i);
return 1;
}
void tiskni(int i)
{
printf("%d \n", i);
}
|
Můžete říct, že na začátek souboru jsem mohl dát
funkci, ale zrovna mě nic lepšího nenapadalo ...
Uvedu příklad prototypu v souboru .h :
/* Soubor Tisk.cpp */
#include <stdio.h>
#include "tisk.h"
void tiskni(int i)
{
printf("%d \n", i);
}
/* Soubor Tisk.h */
void tiskni(int i);
// Toto je funkční prototyp
// funkce tiskni.
/* Soubor Main.cpp */
#include
#include "tisk.h"
// Zde se vloží modul tisk, složený ze
// souborů tisk.cpp a tisk.h
// Nezapomenout na uvozovky v případě
// programátorem vytvořeného modulu
// Oba soubory musí být vložené v projektu
// (pravé myšítko na kartě filewiew, Add files
// to project ...)
int main(void)
{
int i;
for(i = 0; i < 10; i ++)
tiskni(i);
return 1;
}
|
Takhle máte v projektu tři soubory, dva jsou tzv. modul (tisk.c a tisk.h).
To je vlastně základ týmové spolupráce v C-čku. Třeba Quake I : Má modul
pro čtení map, pro čtení textur, pro otvírání PAKů, přehrávání hudby,
klávesnici, kreslení, umělou inteligenci příšer a já nevím co ještě a každej
modul psal někdo jinej. (Quake není nejlepší příklad, tam byli asi jen čtyři
programátoři na čtyřicet souborů) Taky je dobrý dávat do .h komentáře k funkcím,
kdo to napsal, kdy to napsal a co to dělá. Potom když někdo všechny ty moduly
spojuje dohromady a něco nefunguje, může jít a zeptat se / napsat e-mail
nebo se podívat na www. (a nebo jít a dát mu přes hubu :-))
Občas se jěště dělalo že prototypy byly v .c jako extern :
extern void tiskni(int i);
|
a potom tam nemusel být .h, ale to je pěkná prasečina :-) Ale extern se dají použít
když chcete mít proměnné, které jsou sdílené více moduly. V prvním .c jsou proměnné
normálně a v dalších jsou jako extern. Tudíž pokud se změní hodnota v jednom modulu,
změní se i v ostatních.
Je tady jedna specialita, kterou používají profesionálové. Do souboru .h se dá tzv. guard
(tři řádky kódu, bránící dvojitému inkludování souboru) Vypadá takhle :
/* Soubor Tisk.h */
#ifndef TISK_VLOZEN
#define TISK_VLOZEN
void tiskni(int i);
// Toto je funkční prototyp
// funkce tiskni.
#endif
|
Používají to všichni, třeba kus Unreal Enginu (Unreal je obch. známka společnosti
Epic Megagames, inc. - jen pro pořádek) :
/*=============================================================================
Engine.h: Unreal engine header file.
Copyright 1997-1999 Epic Games, Inc. All Rights Reserved.
=============================================================================*/
#ifndef _INC_ENGINE
#define _INC_ENGINE
/*----------------------------------------------------------------------------
API.
----------------------------------------------------------------------------*/
#ifndef ENGINE_API
#define ENGINE_API DLL_IMPORT
#endif
/*-----------------------------------------------------------------------------
Dependencies.
-----------------------------------------------------------------------------*/
#include "Core.h"
/*-----------------------------------------------------------------------------
Global variables.
-----------------------------------------------------------------------------*/
ENGINE_API extern class FMemStack GEngineMem;
ENGINE_API extern class FMemCache GCache;
/*-----------------------------------------------------------------------------
Engine compiler specific includes.
-----------------------------------------------------------------------------*/
#if __GNUG__
#include "UnEngineGnuG.h"
#endif
/*-----------------------------------------------------------------------------
Engine public includes.
-----------------------------------------------------------------------------*/
#include "UnObj.h" // Standard object definitions.
#include "UnPrim.h" // Primitive class.
#include "UnModel.h" // Model class.
#include "UnTex.h" // Texture and palette.
#include "UnAnim.h"
#include "EngineClasses.h" // All actor classes.
#include "UnReach.h" // Reach specs.
#include "UnURL.h" // Uniform resource locators.
#include "UnLevel.h" // Level object.
#include "UnIn.h" // Input system.
#include "UnPlayer.h" // Player class.
#include "UnEngine.h" // Unreal engine.
#include "UnGame.h" // Unreal game engine.
#include "UnCamera.h" // Viewport subsystem.
#include "UnMesh.h" // Mesh objects.
#include "UnSkeletalMesh.h" // Skeletal model objects.
#include "UnActor.h" // Actor inlines.
#include "UnAudio.h" // Audio code.
#include "UnDynBsp.h" // Dynamic Bsp objects.
#include "UnScrTex.h" // Scripted textures.
#include "UnRenderIterator.h" // Enhanced Actor Render Interface
#include "UnRenderIteratorSupport.h"
/*-----------------------------------------------------------------------------
The End.
-----------------------------------------------------------------------------*/
#endif
|
Do souboru .h se taky obvykle dávají struktury, konstanty, enumy, uniony a další potvory.
To je asi všechno, co byste měli znát o funkcích, takže tuto kapitolu končím.
Ještě něco :
Cvičení :
1) - Napište funkci, která rekurzivně spočítá mocninu reálného čísla
2) - Napište funkci Max_Tri, která vrátí největší ze tří čísel
3) - Napište funkci, zjišťující zda je parametr prvočíslo a podle toho vrátí 1 nebo 0
4) - Napište funkci pro převod malých znaků na velké a naopak (v jednom)
5) - Napište funkci, která vypočítá rovnici : x = 7a + 41b - 56c + 14
(a, b, c jsou parametry a x je výsledek)
6) - Napište modul pro výpočet obsahu a obvodu kružnice (v .h použijte guarda)
Toš se mejte ať nesmrdíte ;-)
-tHE SWINe-