Bogdan Kreczmer ZPCiR IIAiR PWr pokój 307 budynek C3 bogdan.kreczmer@pwr.wroc.pl Copyright c 2006 2010 Bogdan Kreczmer Niniejszy dokument zawiera materiały do wykładu na temat programowania obiektowego. Jest on udostępniony pod warunkiem wykorzystania wyłacznie do własnych prywatnych potrzeb i może on być kopiowany wyłacznie w całości, razem z niniejsza strona tytułowa.
Separacja kodu i typów 1 W językach takich jak C i Pascal mamy do czynienia z separacja kodu i typu parametrów. Wartości z jakimi wywoływane sa funkcje i procedury moga parametryzować ich działanie. Jednak ich typy zostaja ustalone raz na zawsze w momencie ich definicji.
Separacja kodu i typów 1 W językach takich jak C i Pascal mamy do czynienia z separacja kodu i typu parametrów. Wartości z jakimi wywoływane sa funkcje i procedury moga parametryzować ich działanie. Jednak ich typy zostaja ustalone raz na zawsze w momencie ich definicji. Problem: Należy zaimplementować algorytm sortowania dla obiektów różnych typów.
Separacja kodu i typów 1 W językach takich jak C i Pascal mamy do czynienia z separacja kodu i typu parametrów. Wartości z jakimi wywoływane sa funkcje i procedury moga parametryzować ich działanie. Jednak ich typy zostaja ustalone raz na zawsze w momencie ich definicji. Problem: Należy zaimplementować algorytm sortowania dla obiektów różnych typów. Możliwe rozwiazania:
Separacja kodu i typów 1 W językach takich jak C i Pascal mamy do czynienia z separacja kodu i typu parametrów. Wartości z jakimi wywoływane sa funkcje i procedury moga parametryzować ich działanie. Jednak ich typy zostaja ustalone raz na zawsze w momencie ich definicji. Problem: Należy zaimplementować algorytm sortowania dla obiektów różnych typów. Możliwe rozwiazania: Implementacja algorytmu dla wszystkich typów, dla których przewidziane jest jego zastosowanie.
Separacja kodu i typów 1 W językach takich jak C i Pascal mamy do czynienia z separacja kodu i typu parametrów. Wartości z jakimi wywoływane sa funkcje i procedury moga parametryzować ich działanie. Jednak ich typy zostaja ustalone raz na zawsze w momencie ich definicji. Problem: Należy zaimplementować algorytm sortowania dla obiektów różnych typów. Możliwe rozwiazania: Implementacja algorytmu dla wszystkich typów, dla których przewidziane jest jego zastosowanie. Implementacja algorytmu dla typu podstawowego takiego jak void lub Object.
Separacja kodu i typów 1 W językach takich jak C i Pascal mamy do czynienia z separacja kodu i typu parametrów. Wartości z jakimi wywoływane sa funkcje i procedury moga parametryzować ich działanie. Jednak ich typy zostaja ustalone raz na zawsze w momencie ich definicji. Problem: Należy zaimplementować algorytm sortowania dla obiektów różnych typów. Możliwe rozwiazania: Implementacja algorytmu dla wszystkich typów, dla których przewidziane jest jego zastosowanie. Implementacja algorytmu dla typu podstawowego takiego jak void lub Object. Zdefiniowanie makr i wykorzystanie specjalnych preprocesorów (np. C/C++). cpp dla
Separacja kodu i typów 1 W językach takich jak C i Pascal mamy do czynienia z separacja kodu i typu parametrów. Wartości z jakimi wywoływane sa funkcje i procedury moga parametryzować ich działanie. Jednak ich typy zostaja ustalone raz na zawsze w momencie ich definicji. Problem: Należy zaimplementować algorytm sortowania dla obiektów różnych typów. Możliwe rozwiazania: Implementacja algorytmu dla wszystkich typów, dla których przewidziane jest jego zastosowanie. Implementacja algorytmu dla typu podstawowego takiego jak void lub Object. Zdefiniowanie makr i wykorzystanie specjalnych preprocesorów (np. C/C++). cpp dla Najlepszym rozwiazaniem dla postawionego problemu jest koncepcja szablonów.
Podstawowe cechy 2 Szablony pozwalaja na definiowanie funkcji, których typy parametrów sa także parametrami tych funkcji.
Podstawowe cechy 2 Szablony pozwalaja na definiowanie funkcji, których typy parametrów sa także parametrami tych funkcji. Możliwe jest definiowanie klas, które parametryzowane moga być typami pól występujacych w tych klasach i/lub też typami parametrów metod.
Podstawowe cechy 2 Szablony pozwalaja na definiowanie funkcji, których typy parametrów sa także parametrami tych funkcji. Możliwe jest definiowanie klas, które parametryzowane moga być typami pól występujacych w tych klasach i/lub też typami parametrów metod. Programista definiuje tylko raz dany szablon. Kompilator dokonuje dedukcji typów parametrów danego szablonu i konkretyzuje go tworzac kod dla użytych typów w wywołaniu funkcji lub definicji obiektu danej klasy.
Podstawowe cechy 2 Szablony pozwalaja na definiowanie funkcji, których typy parametrów sa także parametrami tych funkcji. Możliwe jest definiowanie klas, które parametryzowane moga być typami pól występujacych w tych klasach i/lub też typami parametrów metod. Programista definiuje tylko raz dany szablon. Kompilator dokonuje dedukcji typów parametrów danego szablonu i konkretyzuje go tworzac kod dla użytych typów w wywołaniu funkcji lub definicji obiektu danej klasy. Programista może też jawnie określić wartości parametrów szablonu.
Podstawowe cechy 3 Zalety:
Podstawowe cechy 3 Zalety: Szablony daja możliwość tworzenia uniwersalnych algorytmów i uniwersalnych struktur danych.
Podstawowe cechy 3 Zalety: Szablony daja możliwość tworzenia uniwersalnych algorytmów i uniwersalnych struktur danych. W odróżnieniu od makr możliwe jest zachowanie przejrzystości kodu.
Podstawowe cechy 3 Zalety: Szablony daja możliwość tworzenia uniwersalnych algorytmów i uniwersalnych struktur danych. W odróżnieniu od makr możliwe jest zachowanie przejrzystości kodu. W odróżnieniu od wykorzystywania typów bazowych pozwalaja zachować ścisła kontrolę typów w trakcie kompilacji.
Podstawowe cechy 3 Zalety: Szablony daja możliwość tworzenia uniwersalnych algorytmów i uniwersalnych struktur danych. W odróżnieniu od makr możliwe jest zachowanie przejrzystości kodu. W odróżnieniu od wykorzystywania typów bazowych pozwalaja zachować ścisła kontrolę typów w trakcie kompilacji. Wady:
Podstawowe cechy 3 Zalety: Szablony daja możliwość tworzenia uniwersalnych algorytmów i uniwersalnych struktur danych. W odróżnieniu od makr możliwe jest zachowanie przejrzystości kodu. W odróżnieniu od wykorzystywania typów bazowych pozwalaja zachować ścisła kontrolę typów w trakcie kompilacji. Wady: Brak możliwości tworzenia oddzielnych jednostek kompilacji (modułów) w postaci czystych szablonów.
Szablon funkcji 4 template <class Typ> Typ max( Typ w1, Typ w2 ) return w1 < w2? w2 : w1; enum Symbole a=1, b, c ; int main( ) cout << max(1,2) << endl; cout << max(1.1, 2.2) << endl; cout << max( A, B ) << endl; cout << max( a, b ) << endl;
Szablon funkcji 4 template <class Typ> Typ max( Typ w1, Typ w2 ) return w1 < w2? w2 : w1; enum Symbole a=1, b, c ; int main( ) cout << max(1,2) << endl; cout << max(1.1, 2.2) << endl; cout << max( A, B ) << endl; cout << max( a, b ) << endl; Wynik działania: 2 2.2 B 2
Szablon funkcji 4 template <class Typ> Typ max( Typ w1, Typ w2 ) return w1 < w2? w2 : w1; enum Symbole a=1, b, c ; int main( ) cout << max(1,2) << endl; cout << max(1.1, 2.2) << endl; cout << max( A, B ) << endl; cout << max( a, b ) << endl; Wynik działania: 2 2.2 B 2 W tym przykładzie kompilator generuje kod funkcji max dla czterech przypadków. Słowo kluczowe class może zostać zastapione przez typename.
Szablon funkcji 5 struct Wektor //.................................................................... float x, y; Wektor( float x = 0, float y = 0 ): x(x), y(y) bool operator < ( const Wektor& W ) const return x x+ y y < W. x W. x+w. y W. y; ; //................................................................................... template < typename Typ > Typ max( Typ w1, Typ w2 ) return w1 < w2? w2 : w1; int main( ) Wektor W1(1,1), W2(-2,1); W1 = max( W1, W2 ); cout << W1. x <<, << W1. y << endl;
Szablon funkcji 5 struct Wektor //.................................................................... float x, y; Wektor( float x = 0, float y = 0 ): x(x), y(y) bool operator < ( const Wektor& W ) const return x x+ y y < W. x W. x+w. y W. y; ; //................................................................................... template < typename Typ > Typ max( Typ w1, Typ w2 ) return w1 < w2? w2 : w1; int main( ) Wektor W1(1,1), W2(-2,1); W1 = max( W1, W2 ); cout << W1. x <<, << W1. y << endl; Wynik działania: -2, 1
Szablon funkcji 5 struct Wektor //.................................................................... float x, y; Wektor( float x = 0, float y = 0 ): x(x), y(y) bool operator < ( const Wektor& W ) const return x x+ y y < W. x W. x+w. y W. y; ; //................................................................................... template < typename Typ > Typ max( Typ w1, Typ w2 ) return w1 < w2? w2 : w1; int main( ) Wektor W1(1,1), W2(-2,1); W1 = max( W1, W2 ); cout << W1. x <<, << W1. y << endl; Wynik działania: -2, 1 Szablon funkcji można wykorzystywać dla własnych klas, o ile wszystkie realizowane w nim operacje będa legalne.
Szablon funkcji 6 template <typename Typ> Typ max( Typ w1, Typ w2 ) return cout << S:, w1 < w2? w2 : w1; const char max( const char s1, const char s2 ) return cout << F:, std::strcmp(s1,s2) < 0? s2 : s1; int main( ) cout << max( Abacki, Kowalski ) << endl; cout << max<const char >( Abacki, Kowalski ) << endl; cout << max<>( Abacki, Kowalski ) << endl;
Szablon funkcji 6 template <typename Typ> Typ max( Typ w1, Typ w2 ) return cout << S:, w1 < w2? w2 : w1; const char max( const char s1, const char s2 ) return cout << F:, std::strcmp(s1,s2) < 0? s2 : s1; int main( ) cout << max( Abacki, Kowalski ) << endl; cout << max<const char >( Abacki, Kowalski ) << endl; cout << max<>( Abacki, Kowalski ) << endl; Wynik działania: F: Kowalski S: Abacki S: Abacki
Szablon funkcji 6 template <typename Typ> Typ max( Typ w1, Typ w2 ) return cout << S:, w1 < w2? w2 : w1; const char max( const char s1, const char s2 ) return cout << F:, std::strcmp(s1,s2) < 0? s2 : s1; int main( ) cout << max( Abacki, Kowalski ) << endl; cout << max<const char >( Abacki, Kowalski ) << endl; cout << max<>( Abacki, Kowalski ) << endl; Wynik działania: F: Kowalski S: Abacki S: Abacki Funkcje zdefiniowane przez szablony moga być przeciażone zwykłymi funkcjami. Można jednak wymusić użycie funkcji zdefiniowanej przez szablon.
Szablon funkcji 7 template <typename Typ> Typ max( Typ w1, Typ w2 ) return cout << S:, w1 < w2? w2 : w1; template <> const char max<const char >(const char s1, const char s2) return cout << F:, std::strcmp(s1,s2) < 0? s2 : s1; int main( ) cout << max( Abacki, Kowalski ) << endl; cout << max<const char >( Abacki, Kowalski ) << endl; cout << max<>( Abacki, Kowalski ) << endl;
Szablon funkcji 7 template <typename Typ> Typ max( Typ w1, Typ w2 ) return cout << S:, w1 < w2? w2 : w1; template <> const char max<const char >(const char s1, const char s2) return cout << F:, std::strcmp(s1,s2) < 0? s2 : s1; int main( ) cout << max( Abacki, Kowalski ) << endl; cout << max<const char >( Abacki, Kowalski ) << endl; cout << max<>( Abacki, Kowalski ) << endl; Wynik działania: F: Kowalski F: Kowalski F: Kowalski
Szablon funkcji 7 template <typename Typ> Typ max( Typ w1, Typ w2 ) return cout << S:, w1 < w2? w2 : w1; template <> const char max<const char >(const char s1, const char s2) return cout << F:, std::strcmp(s1,s2) < 0? s2 : s1; int main( ) cout << max( Abacki, Kowalski ) << endl; cout << max<const char >( Abacki, Kowalski ) << endl; cout << max<>( Abacki, Kowalski ) << endl; Wynik działania: F: Kowalski F: Kowalski F: Kowalski Można tworzyć specjalizację szablonu funkcji dla wybranego typu.