Wprowadzenie
W podstawowym programowaniu C++ typ danych, e.sol., int lub char, należy wskazać w deklaracji lub definicji. Wartość taka jak 4 lub 22 lub -5 to int. Wartość taka jak „A” lub „b” lub „c” to znak. Mechanizm szablonów pozwala programiście na użycie typu ogólnego dla zestawu rzeczywistych typów. Na przykład programista może zdecydować się na użycie identyfikatora T dla int lub char. Algorytm C++ może mieć więcej niż jeden typ ogólny. Powiedzmy, że T dla int lub char, U może oznaczać typ zmiennoprzecinkowy lub wskaźnikowy. Klasa, taka jak ciąg znaków lub klasa wektora, jest jak typ danych, a skonkretyzowane obiekty są jak wartości typu danych, który jest określoną klasą. Tak więc mechanizm szablonów pozwala również programiście na użycie ogólnego identyfikatora typu dla zestawu klas.
Szablon C++ tworzy algorytm niezależny od rodzaju użytych danych. Tak więc ten sam algorytm, z wieloma wystąpieniami tego samego typu, może używać różnych typów w różnych wykonaniach. Jednostki zmiennej, funkcji, struktury i klasy mogą mieć szablony. W tym artykule wyjaśniono, jak deklarować szablony, jak definiować szablony i jak je stosować w C++. Powinieneś już mieć wiedzę na temat wyżej wymienionych podmiotów, aby zrozumieć tematy poruszane w tym artykule.
Rodzaje
Skalarny
Typy skalarne to void, bool, char, int, float i pointer.
Klasy jako typy
Konkretną klasę można uznać za typ, a jej obiekty za możliwe wartości.
Typ ogólny reprezentuje zestaw typów skalarnych. Lista typów skalarnych jest obszerna. Na przykład typ int ma inne powiązane typy, takie jak short int, long int itp. Typ ogólny może również reprezentować zestaw klas.
Zmienna
Przykład deklaracji szablonu i definicji jest następujący:
szablonTpi = 3.14;
Zanim przejdziesz dalej, zauważ, że tego rodzaju instrukcja nie może pojawić się w funkcji main() ani w żadnym zakresie bloku. Pierwsza linia to deklaracja nagłówka szablonu, z wybraną przez programistę nazwą typu ogólnego, T. Kolejny wiersz to definicja identyfikatora pi, który jest typu ogólnego T. Precyzję, czy T jest int, float lub jakimś innym typem, można wykonać w funkcji main() C++ (lub innej funkcji). Taka precyzja zostanie zrealizowana ze zmienną pi, a nie T.
Pierwsza linia to deklaracja szablonu-head. Ta deklaracja zaczyna się od słowa zastrzeżonego, szablonu, a następnie nawiasów ostrych otwartych i zamkniętych. W nawiasach kątowych znajduje się co najmniej jeden ogólny identyfikator typu, taki jak T, powyżej. Może istnieć więcej niż jeden identyfikator typu ogólnego, każdy poprzedzony słowem zastrzeżonym typename. Takie ogólne typy w tej pozycji nazywane są parametrami szablonu.
Poniższą instrukcję można zapisać w funkcji main() lub w dowolnej innej funkcji:
Cout << piA funkcja wyświetli 3.14. Wyrażenie pi
W przypadku specjalizacji wybrany typ danych, np. float, umieszczany jest w nawiasach ostrych po zmiennej. Jeśli w deklaracji template-head występuje więcej niż jeden parametr szablonu, w wyrażeniu specjalizacji będzie odpowiednia liczba typów danych w tej samej kolejności.
W specjalizacji typ jest znany jako argument szablonu. Nie myl tego z argumentem funkcji dla wywołania funkcji.
Domyślny typ
Jeśli przy specjalizacji nie podano typu, przyjmuje się typ domyślny. Tak więc z następującego wyrażenia:
szablonU pi = "miłość";
wyświetlacz z:
Cout << pi<> << '\n';
to „miłość” dla stałego wskaźnika do char. Zauważ w deklaracji, że U = const char*. W przypadku specjalizacji nawiasy kątowe będą puste (nie podano typu); rzeczywisty typ jest uważany za stały wskaźnik do char, typ domyślny. Gdyby do specjalizacji potrzebny był inny typ, to nazwa typu byłaby wpisywana w nawiasach ostrych. Gdy typ domyślny jest wymagany przy specjalizacji, powtórzenie typu w nawiasach ostrych jest opcjonalne, i.mi., nawiasy kątowe można pozostawić puste.
Uwaga: domyślny typ można nadal zmienić podczas specjalizacji, mając inny typ.
struktura
Poniższy przykład pokazuje, jak parametr szablonu może być używany ze strukturą:
szablonT Jan = 11;
T Piotr = 12;
T Mary = 13;
T Radość = 14;
;
To są wieki uczniów w klasie (klasie). Pierwsza linia to deklaracja szablonu. Ciało w nawiasach klamrowych jest faktyczną definicją szablonu. Wiek można wyprowadzić w funkcji main() w następujący sposób:
WiecznośćCout << grade7.John << " << grade7.Mary << '\n';
Wyjście to: 11 13. Pierwsza instrukcja tutaj wykonuje specjalizację. Zwróć uwagę, jak to zostało zrobione. Daje również nazwę dla obiektu struktury: grade7. Druga instrukcja zawiera zwykłe wyrażenia obiektów struct. Struktura jest jak klasa. Tutaj Ages jest jak nazwa klasy, podczas gdy grade7 jest obiektem klasy (struct).
Jeśli niektóre przedziały wiekowe są liczbami całkowitymi, a inne zmiennoprzecinkowe, wówczas struktura potrzebuje dwóch parametrów ogólnych, takich jak:
szablonT Jan = 11;
U Piotra = 12.3;
T Mary = 13;
Radość = 14.6;
;
Odpowiedni kod funkcji main() wygląda następująco:
WiecznośćCout << grade7.John << " << grade7.Peter << '\n';
Wyjście to: 11 12.3. Przy specjalizacji kolejność typów (argumentów) musi odpowiadać kolejności typów generycznych w deklaracji.
Deklarację szablonu można oddzielić od definicji w następujący sposób:
szablonJan;
U Piotra;
T Maryja;
U Radość;
;
Wieczność
Pierwszy segment kodu to czysta deklaracja szablonu (nie ma przypisań). Drugi segment kodu, który jest tylko stwierdzeniem, to definicja identyfikatora grade7. Po lewej stronie znajduje się deklaracja identyfikatora, grade7. Po prawej stronie znajduje się lista inicjująca, która przypisuje odpowiednie wartości do członków struktury. Drugi segment (instrukcję) można zapisać w funkcji main(), podczas gdy pierwszy segment pozostaje poza funkcją main().
Nietypowe
Przykłady typów innych niż dane obejmują int, wskaźnik do obiektu, wskaźnik do funkcji i typy auto. Istnieją inne nietypy, których ten artykuł nie dotyczy. Nietyp jest jak niekompletny typ, którego wartość jest podana później i nie można jej zmienić. Jako parametr zaczyna się od określonego nietypu, po którym następuje identyfikator. Wartość identyfikatora jest podawana później, przy specjalizacji i nie może być ponownie zmieniona (jak stała, której wartość jest podana później). Poniższy program ilustruje to:
#zawieraćprzy użyciu standardowej przestrzeni nazw;
szablon
T Jan = N;
U Piotra = 12.3;
T Mary = N;
Radość = 14.6;
;
int main()
Wieczność
Cout << grade7.John << " << grade7.Joy << '\n';
zwróć 0;
Na specjalizacji pierwszy typ, int, w nawiasach ostrych jest bardziej formalny, aby upewnić się, że liczba i kolejność parametrów odpowiada liczbie i kolejności typów (argumentów). Wartość N została podana na specjalizacji. Wyjście to: 11 14.6.
Częściowa specjalizacja
Załóżmy, że szablon ma cztery typy ogólne i że wśród czterech typów potrzebne są dwa typy domyślne. Można to osiągnąć za pomocą konstrukcji częściowej specjalizacji, która nie wykorzystuje operatora przypisania. Tak więc konstrukcja częściowej specjalizacji daje wartości domyślne podzbiorowi typów ogólnych. Jednak w schemacie częściowej specjalizacji potrzebna jest klasa bazowa (struct) i klasa częściowej specjalizacji (struct). Poniższy program ilustruje to dla jednego typu ogólnego z dwóch typów ogólnych:
#zawieraćprzy użyciu standardowej przestrzeni nazw;
//podstawowa klasa szablonu
szablon
struktura Wieki
;
//częściowa specjalizacja
szablon
struktura Wieki
T1 Jan = 11;
pływak Piotr = 12.3;
T1 Maria = 13;
pływak Radość = 14.6;
;
int main()
Wieczność
Cout << grade7.John << " << grade7.Joy << '\n';
zwróć 0;
Zidentyfikuj deklarację klasy bazowej i jej częściową definicję klasy. Deklaracja nagłówka szablonu klasy bazowej zawiera wszystkie niezbędne parametry ogólne. Deklaracja szablonu-head klasy częściowej specjalizacji ma tylko typ ogólny type. W schemacie zastosowano dodatkowy zestaw nawiasów ostrych, który znajduje się zaraz po nazwie klasy w definicji częściowej specjalizacji. To właśnie robi częściowa specjalizacja. Ma typ domyślny i typ inny niż domyślny, w kolejności zapisanej w klasie bazowej. Zauważ, że domyślny typ nadal może mieć inny typ w funkcji main().
Odpowiedni kod w funkcji main() może wyglądać następująco:
WiecznośćCout << grade7.John << " << grade7.Joy << '\n';
Wyjście to: 11 14.6.
Pakiet parametrów szablonu
Pakiet parametrów to parametr szablonu, który akceptuje zero lub więcej typów ogólnych szablonów dla odpowiednich typów danych. Parametr pakietu parametrów zaczyna się od zastrzeżonego słowa typename lub class. Po nim następują trzy kropki, a następnie identyfikator paczki. Poniższy program ilustruje, w jaki sposób pakiet parametrów szablonu może być używany ze strukturą:
#zawieraćprzy użyciu standardowej przestrzeni nazw;
szablon
int Jan = 11;
pływak Piotr = 12.3;
int Maria = 13;
pływak Radość = 14.6;
;
int main()
Wieczność
Cout << gradeB.John << " << gradeB.Mary << '\n';
Wieczność
Cout << gradeC.Peter << " << gradeC.Joy << '\n';
Wieczność
Cout << gradeD.John << " << gradeD.Joy << '\n';
Wiek<> klasa A; //jak domyślne
Cout << gradeA.John << " << gradeA.Joy << '\n';
zwróć 0;
Dane wyjściowe to:
11 1312.3 14.6
11 14.6
11 14.6
Szablony funkcji
Wspomniane wyżej cechy szablonów mają zastosowanie w podobny sposób do szablonów funkcji. Poniższy program pokazuje funkcję z dwoma ogólnymi parametrami szablonu i trzema argumentami:
#zawieraćprzy użyciu standardowej przestrzeni nazw;
szablon
Cout << "There are " << no << " books worth " << cha << str << " in the store." << '\n';
int main()
func(12, '$', "500");
zwróć 0;
Dane wyjściowe są następujące:
W sklepie jest 12 książek o wartości 500$.
Oddzielenie od prototypu
Definicję funkcji można oddzielić od jej prototypu, jak pokazuje poniższy program:
#zawieraćprzy użyciu standardowej przestrzeni nazw;
szablon
szablon
Cout << "There are " << no << " books worth " << cha << str << " in the store." << '\n';
int main()
func(12, '$', "500");
zwróć 0;
Uwaga: Deklaracja szablonu funkcji nie może pojawić się w funkcji main() ani w żadnej innej funkcji.
Przeciążenie
Przeciążanie tej samej funkcji może mieć miejsce przy różnych deklaracjach szablonów-nagłówków. Poniższy program ilustruje to:
#zawieraćprzy użyciu standardowej przestrzeni nazw;
szablon
Cout << "There are " << no << " books worth " << cha << str << " in the store." << '\n';
szablon
Cout << "There are " << no << " books worth $" << str << " in the store." << '\n';
int main()
func(12, '$', "500");
func(12, "500");
zwróć 0;
Dane wyjściowe to:
W sklepie jest 12 książek o wartości 500$.
W sklepie jest 12 książek o wartości 500$.
Szablony zajęć
Wspomniane wyżej cechy szablonów mają zastosowanie w podobny sposób do szablonów klasowych. Poniższy program jest deklaracją, definicją i użyciem prostej klasy:
#zawieraćprzy użyciu standardowej przestrzeni nazw;
klasa TheCla
publiczny:
liczba wewnętrzna;
znak statyczny;
void func (char cha, const char *str)
Cout << "There are " << num << " books worth " << cha << str << " in the store." << '\n';
static void fun (char ch)
jeśli (ch == 'a')
Cout << "Official static member function" << '\n';
;
int main()
Objekt Claa;
obiekt.liczba = 12;
obiekt.func('$', "500");
zwróć 0;
Dane wyjściowe są następujące:
W sklepie jest 12 książek o wartości 500$.
Poniższy program jest powyższym programem z deklaracją szablonu-nagłówka:
#zawieraćprzy użyciu standardowej przestrzeni nazw;
szablon
publiczny:
liczba T;
statyczny Uch;
void func (U cha, const char *str)
Cout << "There are " << num << " books worth " << cha << str << " in the store." << '\n';
pustka statyczna zabawa (U ch)
jeśli (ch == 'a')
Cout << "Official static member function" << '\n';
;
int main()
TheCla
obiekt.liczba = 12;
obiekt.func('$', "500");
zwróć 0;
Zamiast nazwy typu słowa na liście parametrów szablonu można użyć klasy słowa. Zwróć uwagę na specjalizację w deklaracji obiektu. Dane wyjściowe są nadal takie same:
W sklepie jest 12 książek o wartości 500$.
Deklaracja separacji
Deklarację szablonu klasy można oddzielić od kodu klasy w następujący sposób:
szablonszablon
publiczny:
liczba T;
statyczny Uch;
void func (U cha, const char *str)
Cout << "There are " << num << " books worth " << cha << str << " in the store." << '\n';
pustka statyczna zabawa (U ch)
jeśli (ch == 'a')
Cout << "Official static member function" << '\n';
;
Postępowanie z członkami statycznymi
Poniższy program pokazuje, jak uzyskać dostęp do statycznej składowej danych i statycznej funkcji składowej:
#zawieraćprzy użyciu standardowej przestrzeni nazw;
szablon
publiczny:
liczba T;
statyczny Uch;
void func (U cha, const char *str)
Cout << "There are " << num << " books worth " << cha << str << " in the store." << '\n';
pustka statyczna zabawa (U cha)
jeśli (ch == 'a')
Cout << "Official static member function" << cha << '\n';
;
szablon
int main()
TheCla
zwróć 0;
Przypisanie wartości do statycznego elementu danych jest deklaracją i nie może znajdować się w main(). Zwróć uwagę na użycie i pozycje typów ogólnych oraz typu ogólnego danych w instrukcji przypisania. Ponadto należy zauważyć, że funkcja składowa danych statycznych została wywołana w funkcji main() z rzeczywistymi typami danych szablonu template. Dane wyjściowe są następujące:
Oficjalna funkcja statycznego członka.
Kompilacja
Deklaracja (nagłówek) i definicja szablonu muszą znajdować się w jednym pliku. Oznacza to, że muszą znajdować się w tej samej jednostce tłumaczeniowej.
Wniosek
Szablony C++ tworzą algorytm niezależny od rodzaju użytych danych. Jednostki zmiennej, funkcji, struktury i klasy mogą mieć szablony, które obejmują deklarację i definicję. Tworzenie szablonu wiąże się również ze specjalizacją, czyli wtedy, gdy typ ogólny przyjmuje typ rzeczywisty. Oświadczenie i definicja szablonu muszą znajdować się w jednej jednostce tłumaczeniowej.