C++ v rámci větší uživatelské přítulnosti poskytuje kromě přetěžování (overload) funkcí/metod také implicitní (default) hodnoty parametrů funkcí/metod (na rozdíl od Javy, u které mně tento syntaktický cukr celkem chybí). Většina programátorů v C++ o tom ví a tuto skutečnost využívá. Co už se ale ví méně, je to, že implicitního parametr funkce nemusí být konstanta. V tomto příspěvku se nebudu zabývat tím, do jaké míry je to vhodné a použitelné (ve většině případů to totiž opravdu vhodné není), ale pouze tím, co C++ v tomto směru umožňuje.
Standard C++98 říká (sekce 8.3.6 - Default arguments), že implicitním argumentem je výraz (expression). Pro úplnost dodávám, že na tento výraz jsou kladena určitá omezení (např. se nesmí jednat o lokální proměnnou, this
atd., viz norma), ale ukázky v tomto příspěvku budou validní. Jdeme tedy na to.
Implicitní hodnotou parametru je hodnota statické proměnné
Na začátek něco jednoduchého.
#include <iostream> using namespace std; class A { public: static int defX; static void f(int x = defX) { cout << "f(): " << x << endl; } }; int A::defX = 5; int main() { A::f(); // Prints "f(): 5" A::defX = 13; A::f(); // Prints "f(): 13" }
Podobný kód je velice běžný, ovšem s tou výjimkou, že defX
bývá konstanta. Zde tomu ovšem tak není a jak vidíme, tak výstup volání metody A::f()
se liší podle toho, jakou hodnotu má statická proměnná defX
třídy A
.
Implicitní hodnotou parametru je výsledek volání funkce
Nyní něco zajímavějšího.
#include <iostream> #include <cstdlib> using namespace std; class B { public: static void f(int x = rand()) { cout << "f(): " << x << endl; } }; int main() { B::f(); // Prints "f(): 1804289383" B::f(); // Prints "f(): 846930886" }
Norma nám zaručuje, že výraz, který tvoří implicitní hodnotu parametru, bude vyhodnocen při každém volání funkce/metody (což bylo ostatně potřeba už v minulém příkladu). Nic nám tedy nebrání na místo implicitní hodnoty parametru dát volání funkce rand()
(mimochodem, po absolvování kurzu funkcionálních jazyků se mně začíná příčit nazývat "funkci" rand()
funkcí :), ale ve smyslu jazyka C++ to funkce je). Při každém zavolání metody f()
třídy B
tedy dojde k vypsání pseudonáhodného čísla.
Změna hodnoty implicitního parametru změnou deklarace funkce
A nakonec něco divočejšího.
#include <iostream> using namespace std; void f(int x = 2) { cout << "f(): " << x << endl; } int main() { f(); // Prints "f(): 2" void f(int x = 7); f(); // Prints "f(): 7" ::f(); // Prints "f(): 2" }
Po prvním zavolání funkce f()
dojde k výpisu čísla 2, ale stačí na lokální úrovni změnit deklaraci funkce f()
a při jejím následném zavolání dostaneme změněný výpis. Pokud bychom nyní chtěli zavolat funkci f()
z deklarace na globální úrovni, lze použít operátor ::
. Detaily viz norma C++98, sekce 8.3.6.4 a 5.1.4.
Howdy would you mind stating…
Howdy would you mind stating which blog platform you're using?
I'm looking to start my own blog in the near future but I'm having a difficult time
deciding between BlogEngine/Wordpress/B2evolution and Drupal.
The reason I ask is because your design seems
different then most blogs and I'm looking for something completely
unique. P.S Apologies for getting off-topic but I had to ask!
Do you mind if I quote a few…
Do you mind if I quote a few of your posts as long as I provide credit and sources back
to your webpage? My website is in the exact same niche as yours
and my visitors would truly benefit from some of the information you
present here. Please let me know if this alright
with you. Thanks a lot!