[C++] Szablony funkcji, funkcje specjalizowane, szablony klas, funkcje zaprzyjaźnione, specjalizowana klasa szablonowa, zmienne statyczne w szablonach klas, dynamiczne obiekty szablonowe

Przykład zawiera następujące zagadnienia: szablony funkcji, funkcje specjalizowane, szablony klas, funkcje zaprzyjaźnione, specjalizowana klasa szablonowa, zmienne statyczne w szablonach klas, dynamiczne obiekty szablonowe. Kod jest uzupełniony o komentarze które przydadzą się w trakcie jego analizy. Kompilowane pod Visual Studio 2010. [code=cpp] // szablony.cpp : Defines the entry point for the console application. // #include “stdafx.h” #include #include using namespace std; // zwykła funkcja void porownaj(int a, int b) { if(a > b) { cout«a«" jest wieksze od “«b«endl; } else if(a == b) { cout«a«” jest rowne “«b«endl; } else { cout«a«” jest mniejsze od “«b«endl; } }

Przykład zawiera następujące zagadnienia: szablony funkcji, funkcje specjalizowane, szablony klas, funkcje zaprzyjaźnione, specjalizowana klasa szablonowa, zmienne statyczne w szablonach klas, dynamiczne obiekty szablonowe.

Kod jest uzupełniony o komentarze które przydadzą się w trakcie jego analizy. Kompilowane pod Visual Studio 2010.

[code=cpp] // szablony.cpp : Defines the entry point for the console application. //

#include “stdafx.h” #include #include

using namespace std;

// zwykła funkcja void porownaj(int a, int b) { if(a > b) { cout«a«" jest wieksze od “«b«endl; } else if(a == b) { cout«a«” jest rowne “«b«endl; } else { cout«a«” jest mniejsze od “«b«endl; } }

// szablony funkcji nalezy umieszczac w zakresie globalnym template void porownaj2(mojtyp a, mojtyp b) { if(a > b) { cout«a«” jest wieksze od “«b«endl; } else if(a == b) { cout«a«” jest rowne “«b«endl; } else { cout«a«” jest mniejsze od “«b«endl; } }

// funkcja specjalizowana void porownaj2(int a, double b) { cout«“int: “«a«”, double: “«b«endl; }

//========================================================

//szablon klasy template class TSchowek { private: mojtyp Schowek; public: static int Licznik;

TSchowek()
{
	Licznik++;
}

void setSchowek(mojtyp arg)
{
	Schowek = arg;
}

mojtyp getSchowek()
{		
	return Schowek;
}

//deklaracja metody
void setSchowekAndPrint(mojtyp);

// funkcja zaprzyjazniona
// wymagane jest podanie template <class mojtyp> aby funkcja zaprzyjazniona miała faktycznie dostep do prywatnych skladnikow klasy
template <class mojtyp> friend void inspektor(TSchowek<mojtyp> &);

};

// szablon metody zdefinowany na zewnątrz klasy template void TSchowek::setSchowekAndPrint(mojtyp arg) { Schowek = arg; cout«“Ustawiono schowek: “«arg«endl; };

// ustawiamy licznik statyczny na 0. Przypisanie do zmiennej statycznej musi odbywać się na zewnątrz klasy template int TSchowek::Licznik = 0;

// definicja funkcji zaprzyjaznionej z klasa TSchowek // funkcja zaprzyjaźniona musi być funkcją szablonową template void inspektor(TSchowek & obj) { // pobieramy wartosc prywatnej zmiennej klasy dzięki temu, że jest to funkcja zaprzyjaziona cout«“Prywatny składnik schowek: “«obj.Schowek; }

// specjalizowana klasa szablonowa template <> // wymagane jest wpisanie: template <> class TSchowek { private: char Schowek; public: static int Licznik;

TSchowek()
{
	Licznik++;
}

void setSchowek(char arg)
{
	Schowek = arg;
	cout<<"Ustawiono schowek na char: "<<arg;
}

};

// ustawienie zmiennej statycznej int TSchowek::Licznik = 0;

//========================================================

int _tmain(int argc, _TCHAR* argv[]) {

porownaj(3.5,3); // w wyniku da 3 jest rowne 3

porownaj2<double>(3.5,3); // 3.5>3

porownaj2<char>('c','b'); // c>b

// nie trzeba podwac <double> poniewaz na podstawie typu argumentow tworzona jest funkcja z szablonu
porownaj2(12.1,19.54); // 12.1 < 19.54 

// zostanie uzyta funkcja specjalizowana poniewaz pierwszy argument to int a drugi double 
// (zgodnie z definicja funkcji specjalizowanej gdzie argumenty to int,double)
porownaj2(3,4.2); 

// Tutaj tez uruchomi sie funkcja specjalizowana mimo ze jako pierwszy typ podalismy double, a nie int.
// Jest to spowodowane typ ze argumenty roznia sie typami a w szablonie oba argumenty powinny byc takie same by moglby byc uzyte
// Jako drugi argument podalismy int zamiast double.
// Funkcja zwroci double:3, int:3
// W pierwszym argumencie 3.5 zostanie zamienione na 3 bo ten argument ma byc typu int  
porownaj2(3.5,3);

//tez zostanie uzyta funkcja specjalizowana
porownaj2('a',3); //zwroci int: 97, double: 3


cout<<"--------------n";

cout<<"nObiekty TSchowek<int>n";

TSchowek<int> obj;

obj.setSchowek(20);
cout<<"Schowek: "<<obj.getSchowek()<<"n";
cout<<"Licznik statyczny: "<<obj.Licznik<<"n";

TSchowek<int> obj2;
obj2.setSchowekAndPrint(34);
cout<<"Licznik statyczny: "<<obj2.Licznik<<"n"; // wyświetli 2 bo utworzyliśmy dotychczas dwa obiekty typu TSchowek<int> 

inspektor<int>(obj2); // wywołanie funkcji zaprzyjaźnionej z klasą TSchowek



cout<<"nObiekty TSchowek<string>n";

TSchowek<string> obj_string1;

obj_string1.setSchowek("Jakis tekst :)");
cout<<"Schowek: "<<obj_string1.getSchowek()<<"n";

obj_string1.setSchowekAndPrint("Nowy tekst");

cout<<"Licznik statyczny: "<<obj_string1.Licznik<<"n";

TSchowek<string> obj_string2;
cout<<"Licznik statyczny: "<<obj_string2.Licznik<<"n";
TSchowek<string> obj_string3;
// Licznik przechowuje liczbę utworzonych obiektów których typ to TSchowek<string>
// Utworzyliśmy 3 obiekty więc licznik wyświetli liczbę 3
cout<<"Licznik statyczny: "<<obj_string3.Licznik<<"n"; 



cout<<"nDynamiczne obiekty szablonowen";

// dynamiczne obiekty szablonowe
TSchowek<double> *wsk = new TSchowek<double>;
wsk->setSchowek(3.234);	
cout<<"Schowek: "<<wsk->getSchowek()<<"n";
cout<<"Licznik statyczny: "<<wsk->Licznik<<"n"; // licznik wyświetli 1 bo utworzyliśmy tylko jeden obiekt typu TSchowek<double>
delete wsk;

TSchowek<double> *wsk2 = new TSchowek<double>;
wsk2->setSchowek(3.234);	
cout<<"Schowek: "<<wsk2->getSchowek()<<"n";
cout<<"Licznik statyczny: "<<wsk2->Licznik<<"n"; // licznik wyświetli 2 bo utworzyliśmy drugi obiekt typu TSchowek<double>
delete wsk2;

TSchowek<double> obj_double;
cout<<"Licznik statyczny: "<<obj_double.Licznik<<"n"; // licznik wyświetli 3 poniewaz utworzylismy trzeci obiekt typu TSchowek<double> mimo, że nie jest on oparty na wskazniku. Liczy się typ utworzonego obiektu!



cout<<"nObiekty TSchowek<char> (specjalizowana klasa szablonowa)n";
TSchowek<char> obj_char;
obj_char.setSchowek('F');



cout<<"nn";
system("pause");
return 0;

} [/code]