Zalążki artykułów

Szablony funkcji

  • 2010-10-31 18:27
  • 8 komentarzy
  • 695 odsłon
  • Oceń ten tekst jako pierwszy
Artykuł  został umieszczony na liście Zalążków artykułów. Jeżeli możesz rozbuduj go!


Szablony funkcji są sposobem na stworzenie funkcji, która może przyjmować argumenty dowolnych typów.

Przykładowo można stworzyć funkcje, która mnoży dwie liczby:

int pomnoz (int a, int b)
{
    return a * b;
}


Funkcja taka działa poprawnie dla argumentów typu int, gdy wyniknie potrzeba użycia jej dla typu float trzeba będzie ją całą skopiować i zapisać w postaci:

float pomnoz (float a, float b)
{
    return a * b;
}


Jak wiadomo w C++ może istnieć wiele funkcji o tej samej nazwie, różniących się tylko parametrami lub zwracanym typem. Więcej na ten temat w artykule Funkcje.

Potem skopiujemy ją jeszcze kilkakrotnie dla kolejnych typów które będą nam potrzebne, może będzie to unsigned int, char, double itp.

Rozwiązanie to jest mało eleganckie. Ponadto stwarza problemy - jeżeli w pierwszej funkcji wystąpi błąd trzeba będzie go poprawić we wszystkich jej kopiach, lepiej było by gdyby można było zrobić to tylko raz.

Z pomocą przychodzą szablony funkcji.

template <class Typ>
Typ pomnoz (Typ a, Typ b)
{
    return a * b;
}


Taki zapis oznacza, że nie tworzymy funkcji, tylko szablon. Z takiego szablonu będziemy tworzyć funkcje w obrębie programu zastępując słowo Typ pożądanym typem zmiennej.

Słowo kluczowe class przed nazwą parametru szablonu (w tym przypadku Typ) sugeruje, że szablony mogą, a nawet powinny, przyjmować jako argumenty typy zdefiniowane przez użytkownika (Klasy). Ten przykład jednak opiera się na typach wbudowanych dla ułatwienia zrozumienia idei szablonów.

#include <iostream>
 
using namespace std;
 
template <class Typ>
Typ pomnoz (Typ a, Typ b)
{
    return a * b;
}
 
int main()
{
    float fA = 0.3;
    float fB = 0.4;
 
    int iA = 2;
    int iB = 4;
 
    cout << "Wynik mnożenia liczb typu float: " << pomnoz<float>(fA,fB) << endl;
    cout << "Wynik mnożenia liczb typu int: " << pomnoz<int>(iA,iB) << endl;  
 
    return 0;   
}


Proszę zwrócić uwagę na wywołanie funkcji (a właściwie szablonu) pomnoz.

pomnoz<float>(fA,fB)


Oznacza to "zamień słówko Typ w moim szablonie na float" i skutkuje wytworzeniem takiej funkcji:

float pomnoz (float a, float b)
{
    return a * b;
}


Szablony mogą posiadać też więcej niż jeden argument:

#include <iostream>
 
using namespace std;
 
template <class TypPrzyjety, class TypZwracany>
TypZwracany rzutowanie (TypPrzyjety A)
{
    return (TypZwracany) A;
}
 
int main()
{
    float fA = 3.3;
    int iA = 0;
 
    iA = rzutowanie<float,int>(fA);
 
    cout << iA; // wyświetli 3
 
    return 0;   
}


Zobacz też


8 komentarzy

brodny 2006-07-23 20:36

<quote=prgtw>- mała liczba słów kluczowych</quote>
To niekoniecznie wada.

<quote=prgtw>- brak kontroli zakresów np. tablic</quote>
Bo programista sam sprawdza tam, gdzie uważa to za stosowne - zysk na szybkości; zresztą w Pascalu też można wyłączyć sprawdzanie zakresów (Range Checking)

<quote=prgtw>- brak zagnieżdżania funkcji w funkcji - nie w pełni strukturalny</quote>

Zagnieżdżanie funkcji w funkcji w Pascalu tylko spowalnia wykonywanie programu. Zresztą to nie jest jakieś dotkliwe ograniczenie.

<quote=prgtw>- brak wbudowanego typu String, tylko tablice typu char, przez co operowanie na ciągach jest dla początkujących w C++ utrudnione</quote>
Ale w C++ masz klasę std::string ;>

<quote=prgtw>- C++ nie mozna nazwać językiem wysokiego poziomu, ale niskiego też nie - średni poziom</quote>
IMHO jest to język wysokiego poziomu, ale te podziały są "umowne" - zależy jak na co patrzeć ;)

<quote=prgtw>- niektóre kody źródłowe wydają mi się tak nieczytelne że to szok przez te znaki _ np. cdecl, int n itp.;</quote>
W Pascalu też można nieźle zaciemnić i nieładnie pisać kod [diabel] A te podwójne podkreślenia dolne to kwestia przyzwyczajenia, nie wygląda to aż tak źle ;)

<quote=prgtw>wskaźniki do wskaźników (zmiennych wskaźnikowych) np. char **x;</quote>
Też tak można w Pascalu ;)

wil 2006-06-18 22:47

marcinEc dobrze mówi - kto tak wywołuje funkcje:
rzutowanie<float,int>(fA);

to nie html...

marcinEc 2006-04-28 20:18

a po co o tym pisać po raz kolejny...? Hmm, chyba tylko początkujący piszą artykuły, nie mając za sobą doświadczeń i całej tej (trudnej i nieraz całkiem szerokiej) wiedzy...
Ale może kiedyś... :)

Kooba 2006-04-24 17:17

marcinEc: to napisz o tym.. kiedy przyzwyczaicie sie do tego ze 4p uwolniło dokumenty...

marcinEc 2006-04-22 14:52

A co z dedukcją parametrów? przecież nie muszę pisać:
foo<float>(zmf1,zmf2);

Jest jeszcze specjalizacja szablonu.

prgtw 2006-03-26 23:29

OT:
A dlaczego tak napisałeś. Czyżby Pascal był złym językiem? Narazie widzę więcej przeciw niż za:
- mała liczba słów kluczowych
- brak kontroli zakresów np. tablic
- brak zagnieżdżania funkcji w funkcji - nie w pełni strukturalny
- brak wbudowanego typu String, tylko tablice typu char, przez co operowanie na ciągach jest dla początkujących w C++ utrudnione
- C++ nie mozna nazwać językiem wysokiego poziomu, ale niskiego też nie - średni poziom
- niektóre kody źródłowe wydają mi się tak nieczytelne że to szok przez te znaki _ np. cdecl, int n itp.; wskaźniki do wskaźników (zmiennych wskaźnikowych) np. char **x;

Jest też trochę zalet, ale...
Jak możesz to napisz jakie są zalety z Twojego punktu widzenia (kogoś kto - tak myślę - orientuje się już dosyć dobrze).

Marooned 2006-03-26 17:08

hallelujah! another soul saved!

prgtw 2006-03-26 16:56

Powoli (choć nie wiem czemu, bo widzę więcej wad niż zalet) przerzucam się z Pascala na C++. Słyszałem o szablonach funkcji ale nie wiedziałem jak się ich używa, teraz już wiem. Dzięki.

OT: To tak jak w Pascalu funkcje z operatorem overload.