background image

Szablony funkcji

Andrzej Walczak

Konspekt wykładu oparty o literaturę z 

sylabusu

background image

Czy możliwe jest, aby funkcja była w 

pewnym stopniu inteligentna? Czy 

mogłaby samodzielnie dobrać zarówno typ 

argumentów, jak typ wyniku czyli samej 

funkcji?

Tak. Takie zadanie realizuje szablon 

funkcji.

Dzięki temu przy korzystanie ze zmiennych 

o typach własnych nie następuje mylenie 

typów (klas).

background image

Definiowanie szablonu w programie

template 

<class 

pewien_typ> 

pewien_typ 

wieksza(pewien_typ a, pewien_typ b)
 
{ return(a>b)?a:b; }

template to słowo kluczowe inicjujące proces tworzenia szablonu

pewien_typ to nazwa szablonu
 
class  to  słowo  kluczowe  KONIECZNE  aby  powstał  szablon.  Kiedy 
parametrów  szablonu  jest  więcej  niż  jeden,  to  po  przecinku 
powtarzamy słowo class i podajemy kolejną nazwę parametru.
 
wieksza  to  nazwa  przykładowej  funkcji,  która  wybiera  większą  z 
dwóch  liczb.  Typ  argumentów  i  funkcji  jest  przy  tym  dowolny, 
wbudowany lub zdefiniowany przez programującego. Oznacza to, że 
argumentami funkcji mogą być obiekty.

background image

Główne wymagania i cechy 

dotyczące szablonu

background image

Główne wymagania i cechy 

dotyczące szablonu cd.

Operacja zapisana w funkcji poddana jest takim samym regułom 
na  poprawność  operacji  jak  we  wszystkich  innych  funkcjach  , 
czyli  nie  wykona  się  na  przykład  operacja  arytmetyczna  na 
zmiennych znakowych. 

Parametr  szablonu  –  nazwany  jakoś  podczas  deklarowania 
szablonu  –  nie  musi  mieć  tej  samej  nazwy  podczas  definiowania 
szablonu.

Dwa szablony o takiej samej nazwy mogą wystąpić w tym samym 
kodzie.  Należy  tylko  uważać,  aby  jeden  nie  był  szczególnym 
przypadkiem  drugiego.  Wówczas  linker  „nie  wie”  z  którego  ma 
skorzystać.

Szablon  wstawiając  do  wzorca  funkcji  różne  typy 
argumentów tworzy tak naprawdę przeładowanie funkcji
.

Sam  szablon  też  może  być  przeładowany  czyli  w  tym  samym 
zakresie ważności może wystąpić dwa lub kilka razy z taką samą 
nazwą ale różnymi parametrami:

template <class typ> void funkcja (typ, int);

template <class typ> void funkcja (typ, int, float, char);

background image

Główne wymagania i cechy 

dotyczące szablonu

cd.

•Szablon  jest  deklarowany  globalnie,  ale  stosowany  lokalnie. 
Dlatego nie powinien używać nazw zmiennych globalnych.

•UWAGA:  standaryzacja  nie  obejmuje  jeszcze  całości  szablonów. 
Mogą występować kłopoty.

•W  szablonie  możemy  stosować  atrybuty  inline,  extern,  static
Pamiętajmy  jednak,  że  słowo  to  odnosi  się  ostatecznie  nie  do 
szablonu ale do funkcji, która wg tego szablonu zostanie zbudowana:

template <class bb> 

inline

 bb wieksza (bb z1, bb z2)

{ return (z1>z2)? z1:z2; } 

background image

Przykład: (wg Grebosza )

#include <iostream>
template <class nasz_typ>
nasz_typ wieksza(nasz_typ a, nasz_typ b)
{ return (a>b)?a:b;}
///////////////////////////////
void main()
{
int a = 44, b = 88;
double x = 14.2, y = 28.4;
unsigned long la = 987654, lb = 777;
//  nigdzie  nie  ma  deklaracji  konkretnego  typu  funkcji  i  typu 
argumentów
cout<<”wiekszy int:” <<wieksza(a,b)<<endl; 
cout<<”wiekszy double:” <<wieksza(x,y)<<endl; 
cout<<”wiekszy long int:” <<wieksza(la,lb)<<endl; 
cout<<”wiekszy kod ASCII:” <<wieksza(‘a’,’b’)<<endl; 
 

background image

Jeśli parametrów jest więcej niż jeden to każdy 
musi być poprzedzony słowem class (albo słowem 
typename)
. Jeśli typ parametru się powtarza czyli 
są np. dwa parametry typu integer, albo dwa 
parametry są obiektami tej samej klasy, to 
wymienia się je na liście parametrów tylko raz.
Czyli poprawny jest zapis w kodzie:
////
template <class krakow,class warszawa>
void funkcja_opis_miasta(krakow a, krakow b, 
krakow c, warszawa d, warszawa e);
///////

background image

Do  argumentu  funkcji  w  szablonie  możemy  się  odwołać  przez 
referencję.
Referencja  była  zastosowana  do  argumentów  funkcji  wtedy, 
kiedy  zamierzeniem  była  zmiana  wartości  pod  adresem 
zmiennej.
Teraz  przy  zdefiniowaniu  szablonu  możemy  ten  sam  kod 
wykorzystać szerzej.
 
#include<iostream>
#include<conio.h>
#include<string.h>
//////////////
 
template<class sejfik>
void zamiana(sejfik &lewy, sejfik &prawy)
{
sejfik pomocniczy;
pomocniczy=lewy;
lewy=prawy;
prawy=pomocniczy;
 

background image

///////////////////// teraz wg SZABLONU
void main()
{
float a=-7.0,b=23.0;
 
cout<<”przed zamiana\n”
<<”a=”<<a<<”\tb=”<<b<<endl<<”\n”;
zamiana(a,b);
 
cout<<”po zamianie\n”
<<”a=”<<a<<”\tb=”<<b<<endl<<”\n”;
zamiana(a,b);
 
cout<<”po zamianie ponownej\n”
<<”a=”<<a<<”\tb=”<<b<<endl<<”\n”;

background image

char c=‘A’,d=‘B’;
 
cout<<”przed zamiana\n”
<<”c=”<<c<<”\td=”<<d<<endl<<”\n”;
zamiana(c,d);
 
cout<<”po zamianie\n”
<<”c=”<<c<<”\td=”<<d<<endl<<”\n”;
zamiana(c,d);
 
cout<<”po zamianie ponownej\n”
<<”c=”<<c<<”\td=”<<d<<endl<<”\n”;
 
 
}

background image

#include <iostream>

#include <conio.h>

/////////////////////

template <class nasz_typ>

 nasz_typ wieksza(nasz_typ a, nasz_typ b)

{ return (a>b)?a:b;}

//////////////////////

class nowa {public:

double war;

};

Atrybut obiektu argumentem 

funkcji szablonowej

background image

void main(){

double aaaa,bbbb;

nowa rr,rrr;

rr.war=10;

rrr.war=1000;

aaaa=rr.war;

bbbb=rrr.war;

int a=44, b=88;

double x=14.2, y=28.4;

unsigned long la=987654, lb=777;

//char A,B;

cout<<"\ntest"<<wieksza(aaaa,bbbb)<<endl; //atrybut obiektu 
argumentem szablonu

cout<<endl<<"\n";

getch();}

background image

Funkcje specjalizowane 

• template <class parametr1, class 

parametr2> parametr1 sumuj (parametr1 
argument1, parametr2 argument2) { return 
(argument1 + argument2); } 

• char * sumuj (char * argument1, char * 

argument2)

//funkcja specjalizowana 

• { return (*argument1 + *argument2); } 


Document Outline