[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]