Unsere Klasse IntArray dient als gute Alternative zu integrierten array von ganzen zahlen. Aber im Leben kann es erforderlich sein Arrays für die verschiedenen Datentypen. Sie können davon ausgehen, dass der einzige Unterschied die array-Elemente vom Typ double von unserem ist die Art der Daten in den anzeigen, der Rest der Code entspricht wörtlich.
Для решения данной проблемы в С++ введен механизм Vorlagen. В объявлениях классов и функций допускается использование parametrisierte Typen. Arten-Parameter ersetzt werden bei der Kompilierung diesen Typen, integrierten oder bestimmte Benutzer. Wir können eine Vorlage erstellen, in der Array-Klasse, ersetzen Sie in der Klasse IntArray Typ der Elemente int auf verallgemeinerte Typ-Parameter. Позже мы конкретизируем Arten-Einstellungen, setzt man stattdessen echte Typen int, double und string. Im Ergebnis wird die Möglichkeit, diese Konkretisierung so, als ob wir tatsächlich identifiziert drei verschiedene Klassen für diese drei Arten von Daten.
Das ist, wie das Aussehen kann, Vorlage-Klasse Array:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
template <class elemType> class Array { public: explicit Array( int sz = DefaultArraySize ); Array( const elemType *ar, int sz ); Array( const Array &iA ); virtual ~Array() { delete[] _ia; } Array& operator=( const Array & ); int size() const { return _size; } virtual elemType& operator[]( int ix ) { return _ia[ix]; } virtual void sort( int,int ); virtual int find( const elemType& ); virtual elemType min(); virtual elemType max(); protected: void init( const elemType*, int ); void swap( int, int ); static const int DefaultArraySize = 12; int _size; elemType *_ia; }; |
Das Schlüsselwort template sagt, was wird die Vorlage, deren Parameter sind in eckige Klammern (<>). In unserem Fall gibt es nur eine Option elemType; das Schlüsselwort class vor seinem Namen meldet, dass diese Option ist eine Art von.
Bei der Konkretisierung der Klasse-Vorlage Array-Parameter elemType durch die echte Art bei jeder Verwendung, wie im Beispiel gezeigt:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
#include <iostream> #include "Array.h" int main() { const int array_size = 4; // elemType заменяется на int Array<int> ia(array_size); // elemType заменяется на double Array<double> da(array_size); // elemType заменяется на char Array<char> ca(array_size); int ix; for ( ix = 0; ix < array_size; ++ix ) { ia[ix] = ix; da[ix] = ix * 1.75; ca[ix] = ix + 'a'; } for ( ix = 0; ix < array_size; ++ix ) cout << "[ " << ix << " ] ia: " << ia[ix] << "\tca: " << ca[ix] << "\tda: " << da[ix] << endl; return 0; } |
Hier werden drei Instanz der Klasse Array:
1 2 3 |
Array<int> ia(array_size); Array<double> da(array_size); Array<char> ca(array_size); |
Was macht der Compiler, Begegnung mit Anzeige? Fügt Text in die Vorlage ein Array, ersetzt die Option elemType auf die Art, das ist in jedem Fall. Daher, anzeigen der Mitglieder erwerben im ersten Fall dieser Art:
1 2 3 |
// Array<int> ia(array_size); int _size; int *_ia; |
Beachten Sie, dass es in der Genauigkeit entspricht der Definition eines Arrays IntArray.
Für die verbleibenden beiden Fällen erhalten wir den folgenden Code:
1 2 3 4 5 6 7 |
// Array<double> da(array_size); int _size; double *_ia; // Array<char> ca(array_size); int _size; char *_ia; |
Was passiert mit den Funktionen-Mitglieder? In Ihnen ist auch der Typ-Parameter elemType durch die echte Art, aber der Compiler nicht konkretisiert die Funktionen, die werden nicht in irgendeiner Stelle im Programm.
Beim ausführen das Programm dieses Beispiel zeigt das folgende Ergebnis:
1 2 3 4 |
[ 0 ] ia: 0 ca: a da: 0 [ 1 ] ia: 1 ca: b da: 1.75 [ 2 ] ia: 2 ca: c da: 3.5 [ 3 ] ia: 3 ca: d da: 5.25 |
Template-Engine kann in die geerbten Klassen. Hier ist, wie sieht die Definition einer Klasse Vorlage ArrayRC:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
#include <cassert> #include "Array.h" template <class elemType> class ArrayRC : public Array<elemType> { public: ArrayRC( int sz = DefaultArraySize ) : Array<elemType>( sz ) {} ArrayRC( const ArrayRC& r ) : Array<elemType>( r ) {} ArrayRC( const elemType *ar, int sz ) : Array<elemType>( ar, sz ) {} elemType& ArrayRC<elemType>::operator[]( int ix ) { assert( ix >= 0 && ix < Array<elemType>::_size ); return _ia[ ix ]; } private: // ... }; |
Die Substitution der realen Parameter statt Typ-Parameter elemType geschieht wie in der Basis, und in abgeleiteten Klassen.
1 |
ArrayRC<int> ia_rc(10); |
Die Definition der verhält sich genau so, wie die Definition IntArrayRC aus dem vorherigen Abschnitt. Ändern Sie ein Beispiel für die Verwendung der vorherigen Abschnitt.
1 |
swap( ia1, 1, ia1.size() ); |
Vor allem, um оператор // Funktion swap() auch sollte die Vorlage war ungültig, wir brauchen vorstellen Funktion swap() als Vorlage.
1 2 3 4 5 6 7 8 9 |
#include "Array.h" template <class elemType> inline void swap( Array<elemType> &array, int i, int j ) { elemType tmp = array[ i ]; array[ i ] = array[ j ]; array[ j ] = tmp; } |
Bei jedem Aufruf von swap() erzeugt die passende Konkretisierung, das hängt von der Art des Arrays. So sieht das Programm, das Vorlagen Array und ArrayRC:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
#include <iostream> #include "Array.h" #include "ArrayRC.h" template <class elemType> inline void swap( Array<elemType> &array, int i, int j ) { elemType tmp = array[ i ]; array[ i ] = array[ j ]; array[ j ] = tmp; } int main() { Array<int> ia1; ArrayRC<int> ia2; cout << "swap() with Array<int> ia1" << endl; int size = ia1.size(); swap( ia1, 1, size ); cout << "swap() with ArrayRC<int> ia2" << endl; size = ia2.size(); swap( ia2, 1, size ); return 0; } |