szablony w C++, Programowanie obiektowe


Szablony klas i funkcji

Przepisz poniższy fragment kodu, zawierający cztery definicje funkcji max, używając szablonu funkcji, tak by zamiast czterech definicji mieć jedną

#include <iostream.h>

int max(int a, int b);

char max (char a, char b);

float max (float a, float b);

bool max (bool a, bool b);

void main()

{

int i1=1,i2=2;

char c1='S', c2='T';

float f1=1.2, f2=0.3;

bool b1=true, b2=false;

cout << "Maksimum z int: "<< max (i1,i2) << endl;

cout << "Maksimum z char: "<< max (c1,c2) << endl;

cout << "Maksimum z flaot: "<< max (f1,f2) << endl;

cout << "Maksimum z bool: "<< max (b1,b2) << endl;

}

int max(int a, int b)

{

if(a>b) return a;

else return b;

}

char max (char a, char b)

{

if(a>b) return a;

else return b;

}

float max (float a, float b)

{

if(a>b) return a;

else return b;

}

bool max (bool a, bool b)

{

if(a>b) return a;

else return b;

}

Rozwiązanie:

#include <iostream.h>

  1. template <typename dowolny_typ >

  2. dowolny_typ max(dowolny_typ a, dowolny_typ b)

{

if(a>b) return a;

else return b;

}

void main()

{

int i1=1,i2=2;

char c1='S', c2='T';

float f1=1.2, f2=0.3;

bool b1=true, b2=false;

  1. cout << "Maksimum z bool: "<< max(b1,b2) << endl;

  2. cout << "Maksimum z int: "<< ::max(i1,i2) << endl;

  3. cout << "Maksimum z flaot: "<< ::max<>(f1,f2) << endl;

  4. cout << "Maksimum z char: "<< ::max<int>(c1,c2)

<< endl;

}

Wynik wykonania:

Maksimum z bool: 1

Maksimum z int: 2

Maksimum z flaot: 1.2

Maksimum z char: 84

Zgodnie z tym co oczekiwano otrzymano kolejno maksymalne wartości:

    1. Słowo kluczowe template informuje kompilator, że dokonamy definicji szablonu funkcji. max. Po słowie kluczowym typename podajemy nazwy parametrów używanych w szablonie (słowo kluczowe typename może być zastąpione słowem class, są one wymienne)...

    2. ... ciąg dalszy definicji szablonu funkcji max. Będzie ona przyjmować dwa argumenty a i b o dowolnym typie (dowolny_typ), zaś będzie zwracać typ taki jak typ parametrów;

    3. wywołana jest funkcja max z parametrami typu bool, czyli następuje konkretyzacja funkcji z parametrami bool;

    4. w dalszym ciągu kompilator dedukuje typ zmiennych i na tej podstawie konkretyzuje funkcje;

    5. dodanie do wywołania funkcji dodatkowych znaków ::max<> wskazuje również aby samodzielnie wydedukował typ zmiennych;

    6. istnieje możliwość podania kompilatorowi w jaki sposób ma być skonkretyzowana funkcja. Powyżej nakazano aby parametry potraktować jak zmienne typu char. Stad zmienne char zostały zrzutowane na int.

W ćwiczeniu tym zostanie przeprowadzony eksperyment, który będzie miał na celu określenie kiedy jest używany szablon a kiedy zwykła funkcja. W tym celu należy zdefiniować szablon i funkcje o takiej samej nazwie i takiej samej liście argumentów, a następnie wywołać ją i sprawdzić, która wersja się uruchomiła.

#include <string>

#include <iostream>

template<typename T> // Definicja szablonu

std::string funkcja(T){

return “Wita szablon!”;

}

std::string f(int&){ // Definicja zwyklej funkcji

return “Wita funkcja!”;

}

int main(){

int x = 7; // Parametr dla funkcji

std::cout<< f(x) << std::endl; // Wywolanie funkcji

};

Zdefiniuj szablon funkcji do obliczania minimum z dwóch liczb.

Zdefiniuj szablon funkcji do obliczania maksimum z dwóch liczb. Jednak tym razem liczby te mogą być różnego typu, tak by było możliwe wpisanie np. max(1, `s'), albo max(3.4 , true). Dla uproszczenia niech typem zwracanym będzie liczba całkowita 1, jeśli pierwszy argument jest większy od drugiego, 0 - w przeciwnym wypadku.

template <typename typ1, typename typ2 >

int max(typ1 a, typ2 b)

{

if(a>b) return 1;

else return 0;

}

Zdefiniuj szablon funkcji typu inline dla utworzonej poprzednio funkcji max.

template <typename typ >

inline typ max(typ a, typ b)

{

if(a>b) return a;

else return b;

}

Jeśli chcielibyśmy utworzyć funkcje z przydomkiem static lub extern to słówko to wpisalibyśmy w miejscu słowa inline.

Zdefiniuj szablon funkcji do obliczania sumy dwóch liczb. Jednak liczby te mają być różnego typu, tak by było możliwe wpisanie np. suma(1, `S'), albo suma(3.4 , true). Dodatkowo niech będzie możliwe zdefiniowanie typu rezultatu sumy (sic!)

template <typename typ1, typename typ2, typename typ_rezultatu >

typ_rezultatu suma(typ1 a, typ2 b, typ_rezultatu)

{

return (a+b);

}

Użycie:

cout << suma(1, `S', (char)1) << endl;

cout << suma(3.4, 3, (float)4) << endl;

Wynik wykonania:

T

6.4

Zdefiniuj szablon funkcji max jak w poprzednich ćwiczeniach, jednak tym razem należy dodać taką regułę przy porównywaniu łańcuchów znaków: „większy łańcuch to ten, który ma większą liczbę znaków”.

#include <iostream.h>

#include <string.h>

template <typename dowolny_typ >

dowolny_typ max(dowolny_typ a, dowolny_typ b)

{

if(a>b)

return a;

else

return b;

}

char* max(char* a, char* b)

{

if(strlen(a)>strlen(b)) return a;

else return b;

}

void main()

{

int i1=2, i2=5;

char s1[]=”olo”, s2[]=”bardzo długi napis..”;

cout << max(i1, i2) << endl

<< max(s1, s2) << endl;

}

Napisz funkcje do sortowania (np. metodą bąbelkową) dowolnych danych.

// Szablon funkcji do sorotowania

template <class T> void sortuj (T *w, const int ile);

void main()

{

int t1[6] ={13,21,5,0,-2,3};

float t2[6] = {0.2, -1.1, 4.6, 3.1, 1.0, 3.3};

sortuj(t1, 6); //wywołanie funkcji dla elementów typu int

sortuj(t2, 6); //wywołanie funkcji dla elementów typu float

}

// Definicja szablonu

template <class T> void sortuj (T *w, const int ile)

{

for (int i= 0; i < ile-1; i++)

for (int j=0; j <ile-1-i; j++)

if (w[j] > w[j+1])

{ T pom = w[j];

w[j] = w[j+1];

w[j+1]= pom;

}

}

Zdefiniuj klasę Schowek do przechowywania zmiennej dowolnego typu o nazwie zawartość. Dodatkowo można zdefiniować dla tej klasy konstruktor i funkcję zwracającą zawartość schowka. Definicja konstruktora i destruktora niech będzie w ciele klasy.

#include <iostream.h>

  1. template <class T>

  1. class Schowek {

  2. T zawartosc;

public:

  1. Schowek(T zaw) {zawartosc = zaw;}

  2. T pobierz() {return zawartosc;}

};

void main(int argc, char* argv[])

{

  1. Schowek<int> s1(10);

  2. Schowek<char> s2('s');

  1. cout << s1.pobierz() << endl

<< s2.pobierz() << endl;

}

Wynik wykonania:

10

s

1 - 2: definicja szablonu klasy, poszczególne klasy utworzone na podstawie tej klasy będą się różnić typem argumentu T.

3 - 5: …cd. definicji szablonu klasy Schowek ze zmienną zawartosc dowolnego typu oraz konstruktorem i metodą pobierz().

6: utworzenie obiektu klasy Schowek o nazwie s1. Jest on utworzony na podstawie szablonu klasy Schowek. Konkretyzujemy, że ma on mieć zawartosc typu int. Dodatkowo inicjalizujemy go wartością 10.

11: utworzenie obiektu klasy Schowek o nazwie s2. Konkretyzujemy, że ma on mieć zawartosc typu char. Dodatkowo inicjalizujemy go wartością `s'.

8: sprawdzenie czy rzeczywiście obiekty zawierają zmienne podanego typu. Potwierdzają to wyniki, kolejno:

10

s

Zdefiniuj klasę Schowek jak w poprzednim ćwiczeniu. Jednak tym razem definicja konstruktora i destruktora niech będą poza ciałem klasy.

#include <iostream.h>

  1. template <class T>

  1. class Schowek {

  2. T zawartosc;

public:

  1. Schowek(T zaw);

  2. T pobierz();

};

  1. template <class T>

  2. Schowek<T>::Schowek(T zaw){

zawartosc = zaw;

}

  1. template <class T>

  2. T Schowek<T>::pobierz(){

return zawartosc;

}

void main(int argc, char* argv[])

{

  1. Schowek<int> s1(10);

  2. Schowek<char> s2('s');

  1. cout << s1.pobierz() << endl

<< s2.pobierz () << endl;

}

Wynik wykonania:

10

s

1: rozpoczęcie definicji szablonu klasy, poszczególne klasy utworzone na podstawie tej klasy będą się różnić typem argumentu T…

2 - 5: …cd. definicji szablonu klasy Schowek ze zmienną zawartosc oraz konstruktorem i metodą pobierz().

6 - 7: definiujemy szablon konstruktora dla klasy Schowek. Zapis Schowek<T>:: informuje kompilator, że ma do czynienia z definicją składnika szablonu klasy, czytając dalej Schowek(T zaw) ”dowie się”, że jest to konstruktor, przyjmujący jeden argument typu T.

8, 9: podobnie przy definicji funkcji pobierz w linii 8,9.

10: utworzenie obiektu klasy Schowek o nazwie s1. Jest on utworzony na podstawie szablonu klasy Schowek. Konkretyzujemy, że ma on mieć zawartosc typu int. Dodatkowo inicjalizujemy go wartością 10.

11: utworzenie obiektu klasy Schowek o nazwie s2. Konkretyzujemy, że ma on mieć zawartosc typu char. Dodatkowo inicjalizujemy go wartością `s'.

12: sprawdzenie czy rzeczywiście obiekty zawierają zmienne podanego typu. Potwierdzają to wyniki, kolejno:

10

s

Utwórz obiekty klasy Schowek do przechowywania:

#include <iostream.h>

template <class T>

class Schowek {

T zawartosc;

public:

Schowek(T zaw) {zawartosc = zaw;}

T pobierz() {return zawartosc;}

};

void main(int argc, char* argv[])

{

Schowek<int> s1(10);

Schowek<char> s2('s');

Schowek<int*> s3;

Schowek<float[5]> s4;

Schowek<Schowek<bool>> s5;

Schowek<Schowek<float>[4]> s6;

}

Implementacja szablonu klasy Stos do przechowywania dowolnych wektorów danych.

#include <vector>

#include <stdexcept>

template <typename T>

class Stos {

private:

std::vector<T> elem: //elementy

public:

void wstaw(T const&); //wstawia element na szczyt stosu

void zdejm(); //zdejmuje element za szczytu stosu

T zwroc(); //zwraca szczytowy element stosu

Bool pusty(){ //czy stos jest pusty?

return elem.empty();

}

};

template <typename T>

void Stos<T>::wstaw (T const& el)

{

elem.push_back(el); //dołącz kopię przekazanego elementu

}

template <typename T>

void Stos<T>::zdejm()

{

if (elem.empty()) {

throw std::out_of_range(“Stos<>::zdejm(): stos jest pusty”);

}

elem.pop_back() //usuń ostatni element

}

template <typename T>

T Stos<T>::zwroc()

{

if (elem.empty()) {

throw std::out_of_range(“Stos<>::zwroc(): stos jest pusty”);

}

return elem.back() //zwróć kopię ostatniego elementu

}

Do poprzedniego ćwiczenia podaj sposoby użycia szablonu klasy Stos.

#include <iostream>

#include <string>

#include <cstdlib>

#include “stos.hpp”

int main()

{

try {

Stos<int> intStos; //stos elementów typu int

Stos<std::string> stringStos; //stos elem typu std::string

//manipuluj stosem elementów typu int

intStos.wstaw(7);

std::cout << intStos.zwroc() << std::endl;

// manipuluj stosem elemetów typu std::string

stringStos.wstaw(„Ahoj”);

std::cout<<stringStack.zwroc() << std::endl;

stringStack.zdejm();

stringStack.zdejm();

}

catch (std::exception const& ex) {

std:cerr << “Wyjątek: “ << ex.what() << std::endl;

return EXIT_FAILURE; //opuść program zwracając kod błędu

}

}

Literatura :

3



Wyszukiwarka

Podobne podstrony:
Programowanie obiektowe(ćw) 1
Zadanie projekt przychodnia lekarska, Programowanie obiektowe
Programowanie obiektowe w PHP4 i PHP5 11 2005
Programowanie Obiektowe ZadTest Nieznany
Egzamin Programowanie Obiektowe Głowacki, Programowanie Obiektowe
Jezyk C Efektywne programowanie obiektowe cpefpo
Programowanie Obiektowe Ćwiczenia 5
Programowanie obiektowe(cw) 2 i Nieznany
programowanie obiektowe 05, c c++, c#
Intuicyjne podstawy programowania obiektowego0
Programowanie obiektowe, CPP program, 1
wyklad5.cpp, JAVA jest językiem programowania obiektowego
projekt01, wisisz, wydzial informatyki, studia zaoczne inzynierskie, programowanie obiektowe, projek
przeciazanie metod i operatorow, Programowanie obiektowe
projekt06, wisisz, wydzial informatyki, studia zaoczne inzynierskie, programowanie obiektowe, projek
projekt07, wisisz, wydzial informatyki, studia zaoczne inzynierskie, programowanie obiektowe, projek
Programowanie Obiektowe Cz2, Dziedziczenie proste
Programowanie obiektowe, w2, 2

więcej podobnych podstron