Szablony funkcji
Artykuł Szablony_funkcji 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:
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:
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.
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;
}
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:
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;
}
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;
}



To niekoniecznie wada.
prgtw napisał:
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)
prgtw napisał:
Zagnieżdżanie funkcji w funkcji w Pascalu tylko spowalnia wykonywanie programu. Zresztą to nie jest jakieś dotkliwe ograniczenie.
prgtw napisał:
Ale w C++ masz klasę std::string ;>
prgtw napisał:
IMHO jest to język wysokiego poziomu, ale te podziały są "umowne" - zależy jak na co patrzeć
prgtw napisał:
W Pascalu też można nieźle zaciemnić i nieładnie pisać kod
prgtw napisał:
Też tak można w Pascalu
rzutowanie<float,int>(fA);
to nie html...
Ale może kiedyś...
foo<float>(zmf1,zmf2);
Jest jeszcze specjalizacja szablonu.
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).
OT: To tak jak w Pascalu funkcje z operatorem overload.