2017年計(jì)算機(jī)等級(jí)考試二級(jí)C++輔導(dǎo):從STL中學(xué)習(xí)泛型編程

字號(hào):


    最近在看數(shù)據(jù)結(jié)構(gòu)方面的書籍,遇到了泛型編程方面的問題,以前遇到的泛型編程問題不多,大多數(shù)也已經(jīng)遺忘,于是打算重新?lián)炱饋?。下面一段關(guān)于泛型編程的定義摘抄于百度百科,應(yīng)該能概括什么事泛型編程。
    泛型編程讓你編寫完全一般化并可重復(fù)使用的算法,其效率與針對(duì)某特定數(shù)據(jù)類型而設(shè)計(jì)的算法相同。泛型編程的代表作品STL是一種高效、泛型、可交互操作的軟件組件。所謂泛型(Genericity),是指具有在多種數(shù)據(jù)類型上皆可操作的含意,與模板有些相似。STL巨大,而且可以擴(kuò)充,它包含很多計(jì)算機(jī)基本算法和數(shù)據(jù)結(jié)構(gòu),而且將算法與數(shù)據(jù)結(jié)構(gòu)完全分離,其中算法是泛型的,不與任何特定數(shù)據(jù)結(jié)構(gòu)或?qū)ο箢愋拖翟谝黄?。STL以迭代器 (Iterators)和容器(Containers)為基礎(chǔ),是一種泛型算法(Generic Algorithms)庫,容器的存在使這些算法有東西可以操作。STL包含各種泛型算法(algorithms)、泛型指針(iterators)、泛型容器(containers)以及函數(shù)對(duì)象(function objects)。STL并非只是一些有用組件的集合,它是描述軟件組件抽象需求條件的一個(gè)正規(guī)而有條理的架構(gòu)。
    上面的概括只是從理論上解釋了什么是泛型,可是看過后還是不知道怎么使用泛型,于是乎筆者找到了STL中定義的頭文件,下面就一步一步解開泛型的秘密。
    由于原版的STL中很多類的套嵌,不便于解釋,所以簡化了STL,以下以vector容器為例:
    文件名:vector.h
    1: template //模板定義了Object類型,在使用的時(shí)候可以以任何類型代替此類型
    2: class vector
    3: {
    4: public:
    5: explicit vector( int initSize = 0 ) : theSize( initSize ), theCapacity( initSize + SPARE_CAPACITY )//重點(diǎn)注意構(gòu)造函數(shù)的定義,構(gòu)造函數(shù)支持兩種方式初始化vector容器,這下知道怎么用vector了吧
    6: { objects = new Object[ theCapacity ]; }
    7: vector( const vector & rhs ) : objects( NULL )
    8: { operator=( rhs ); }
    9: ~vector( )
    10: { delete [ ] objects; }
    11:
    12: bool empty( ) const
    13: { return size( ) == 0; }
    14: int size( ) const
    15: { return theSize; }
    16: int capacity( ) const
    17: { return theCapacity; }
    18:
    19: Object & operator[]( int index )
    20: {
    21: #ifndef NO_CHECK
    22: if( index < 0 || index >= size( ) )
    23: throw ArrayIndexOutOfBoundsException( index, size( ) );
    24: #endif
    25: return objects[ index ];
    26: }
    27:
    28: const Object & operator[]( int index ) const
    29: {
    30: #ifndef NO_CHECK
    31: if( index < 0 || index >= size( ) )
    32: throw ArrayIndexOutOfBoundsException( index, size( ) );
    33: #endif
    34: return objects[ index ];
    35: }
    36:
    37: const vector & operator = ( const vector & rhs );
    38: void resize( int newSize );
    39: void reserve( int newCapacity );
    40:
    41: // Stacky stuff
    42: void push_back( const Object & x );
    43: void pop_back( );
    44: const Object & back ( ) const;
    45:
    46: // Iterator stuff: not bounds checked
    47: typedef Object * iterator;
    48: typedef const Object * const_iterator;
    49:
    50: iterator begin( )
    51: { return &objects[ 0 ]; }
    52: const_iterator begin( ) const
    53: { return &objects[ 0 ]; }
    54: iterator end( )
    55: { return &objects[ size( ) ]; }
    56: const_iterator end( ) const
    57: { return &objects[ size( ) ]; }
    58:
    59: enum { SPARE_CAPACITY = 16 };
    60:
    61: private:
    62: int theSize;
    63: int theCapacity;
    64: Object * objects;
    65: };
    文件名:vector.cpp
    1: template //模板定義了Object類型,在使用的時(shí)候可以以任何類型代替此類型
    2: const vector & vector::operator=( const vector & rhs )//重載賦值操作符
    3: {
    4: if( this != &rhs )//優(yōu)化a=a的情況
    5: {
    6: delete [ ] objects;
    7: theSize = rhs.size( );
    8: theCapacity = rhs.theCapacity;
    9:
    10: objects = new Object[ capacity( ) ];
    11: for( int k = 0; k < size( ); k++ )
    12: objects[ k ] = rhs.objects[ k ];
    13: }
    14: return *this;
    15: }
    16:
    17: //以下為一些常用操作函數(shù)的定義
    18:
    19: template
    20: void vector::resize( int newSize )
    21: {
    22: if( newSize > theCapacity )
    23: reserve( newSize * 2 );
    24: theSize = newSize;
    25: }
    26:
    27:
    28: template
    29: void vector::reserve( int newCapacity )
    30: {
    31: Object *oldArray = objects;
    32:
    33: int numToCopy = newCapacity < theSize ? newCapacity : theSize;
    34: newCapacity += SPARE_CAPACITY;
    35:
    36: objects = new Object[ newCapacity ];
    37: for( int k = 0; k < numToCopy; k++ )
    38: objects[ k ] = oldArray[ k ];
    39:
    40: theSize = numToCopy;
    41: theCapacity = newCapacity;
    42:
    43: delete [ ] oldArray;
    44: }
    45:
    46:
    47: template
    48: void vector::push_back( const Object & x )
    49: {
    50: if( theSize == theCapacity )
    51: reserve( 2 * theCapacity + 1 );
    52: objects[ theSize++ ] = x;
    53: }
    54:
    55:
    56: template
    57: void vector::pop_back( )
    58: {
    59: if( empty( ) )
    60: throw UnderflowException( "Cannot call pop_back on empty vector" );
    61: theSize--;
    62: }
    63:
    64:
    65: template
    66: const Object & vector::back( ) const
    67: {
    68: if( empty( ) )
    69: throw UnderflowException( "Cannot call back on empty vector" );
    70: return objects[ theSize - 1 ];
    71: }