閱讀C++原始碼必備

zzhays發表於2012-09-20

1,預處理指令

C++的預處理(Preprocess),是指在C++程式原始碼被編譯之前,由前處理器(Preprocessor)對C++程式原始碼進行的處理。這個過程並不對程式的原始碼進行解析,但它把源代分割或處理成為特定的符號用來支援巨集調呼叫。

常用指令:

      #include 包含標頭檔案

       #if 條件
  #else 否則
  #elif 否則如果
  #endif 結束條件
  #ifdef 或 #if defined 如果定義了一個符號, 就執行操作
  #ifndef 或 #if !defined 如果沒有定義一個符號,就指執行操作
  #define 定義一個符號
  #undef 刪除一個符號
  #line 重新定義當前行號和檔名
  #error 輸出編譯錯誤 訊息, 停止編譯
  #pragma 提供 機器專用的特性,同時保證與C++的完全相容

2,模板用法 :

template:酷勤

1. 模板的概念。

我們已經學過過載(Overloading),對過載函式而言,C++的檢查機制能通過函式引數的不同及所屬類的不同。正確的呼叫過載函式。例如,為求兩個數的最大值,我們定義MAX()函式需要對不同的資料型別分別定義不同過載(Overload)版本。

//函式1.

int max(int x,int y);
{return(x>y)?x:y ;}

//函式2.
float max( float x,float y){
return (x>y)? x:y ;}

//函式3.
double max(double x,double y)
{return (c>y)? x:y ;}

但如果在主函式中,我們分別定義了 char a,b; 那麼在執行max(a,b);時 程式就會出錯,因為我們沒有定義char型別的過載版本。

現在,我們再重新審視上述的max()函式,它們都具有同樣的功能,即求兩個數的最大值,能否只寫一套程式碼解決這個問題呢?這樣就會避免因過載函式定義不 全面而帶來的呼叫錯誤。為解決上述問題C++引入模板機制,模板定義:模板就是實現程式碼重用機制的一種工具,它可以實現型別引數化,即把型別定義為引數, 從而實現了真正的程式碼可重用性。模版可以分為兩類,一個是函式模版,另外一個是類模版。

2.   函式模板的寫法

函式模板的一般形式如下:

Template <class或者也可以用typename T>

返回型別 函式名(形參表)
{//
函式定義體 }

說明: template是一個宣告模板的關鍵字,表示宣告一個模板關鍵字class不能省略,如果型別形參多餘一個 ,每個形參前都要加class <型別 形參表>可以包含基本資料型別可以包含類型別.

請看以下程式:

//Test.cpp

#include <iostream>

using std::cout;

using std::endl;

//宣告一個函式模版,用來比較輸入的兩個相同資料型別的引數的大小,class也可以被typename代替,

//T可以被任何字母或者數字代替。

template <class T>

T min(T x,T y)

return(x<y)?x:y;}

void main( )

{

     int n1=2,n2=10;

     double d1=1.5,d2=5.6;

     cout<< "較小整數:"<<min(n1,n2)<<endl;

     cout<< "較小實數:"<<min(d1,d2)<<endl;

     system("PAUSE");

}

程式執行結果: 

 

程式分析:main()函式中定義了兩個整型變數n1 , n2 兩個雙精度型別變數d1 , d2然後呼叫min( n1, n2); 即例項化函式模板T min(T x, T y)其中T為int型,求出n1,n2中的最小值.同理呼叫min(d1,d2)時,求出d1,d2中的最小值.

3. 類别範本的寫法

定義一個類别範本:

Template < class或者也可以用typename T >
class類名{
//類定義......
};

說明:其中,template是宣告各模板的關鍵字,表示宣告一個模板,模板引數可以是一個,也可以是多個。

例如:定義一個類别範本:

// ClassTemplate.h
#ifndef ClassTemplate_HH

#define ClassTemplate_HH

template<typename T1,typename T2>

class myClass{

private:

     T1 I;

     T2 J;

public:

     myClass(T1 a, T2 b);//Constructor

     void show();

};

//這是建構函式

//注意這些格式

template <typename T1,typename T2>

myClass<T1,T2>::myClass(T1 a,T2 b):I(a),J(b){}

//這是void show();

template <typename T1,typename T2>

void myClass<T1,T2>::show()

{

     cout<<"I="<<I<<", J="<<J<<endl;

}

#endif

// Test.cpp

#include <iostream>

#include "ClassTemplate.h"

using std::cout;

using std::endl;

void main()

{

     myClass<int,int> class1(3,5);

     class1.show();

     myClass<int,char> class2(3,"a");

     class2.show();

     myClass<double,int> class3(2.9,10);

     class3.show();

     system("PAUSE");

}

最後結果顯示:

 

4.非型別模版引數

一般來說,非型別模板引數可以是常整數(包括列舉)或者指向外部連結物件的指標。

那麼就是說,浮點數是不行的,指向內部連結物件的指標是不行的。


template<typename T, int MAXSIZE>

class Stack{

Private:

       T elems[MAXSIZE];

};

Int main()

{

       Stack<int, 20> int20Stack;

       Stack<int, 40> int40Stack;

};

 51CTO網站http://developer.51cto.com/art/201002/182202.htm  

C++程式語言中的模板應用在一定程度上大大提高了程式開發的效率。我們在這篇文章中為大家詳細講解一下有關C++模板的基本概念,希望初學者們可以通過本文介紹的內容充分掌握這方面的知識。

前段時間重新學習C++,主要看C++程式設計思想和C++設計新思維。對模版的使用有了更進一層的瞭解,特總結如下:

下面列出了C++模板的常用情況:

1. C++模板類靜態成員

  1. template < typename T> struct testClass   
  2. {   
  3. static int _data;   
  4. };   
  5. template< > int testClass< char>::_data = 1;   
  6. template< > int testClass< long>::_data = 2;   
  7. int main( void ) {   
  8. cout < <  boolalpha < <  (1==testClass< char>::_data) < <  endl;   
  9. cout < <  boolalpha < <  (2==testClass< long>::_data) < <  endl;   
  10. }  

2. C++模板類偏特化

  1. template < class I, class O> struct testClass   
  2. {   
  3. testClass() { cout < <  "I, O" < <  endl; }   
  4. };   
  5. template < class T> struct testClass< T*, T*>   
  6. {   
  7. testClass() { cout < <  "T*, T*" < <  endl; }   
  8. };   
  9. template < class T> struct testClass< const T*, T*>   
  10. {   
  11. testClass() { cout < <  "const T*, T*" < <  endl; }   
  12. };   
  13. int main( void )   
  14. {   
  15. testClass< int, char> obj1;   
  16. testClass< int*, int*> obj2;   
  17. testClass< const int*, int*> obj3;   

3.類模版+函式模版

  1. template < class T> struct testClass   
  2. {   
  3. void swap( testClass< T>& ) { cout < <  "swap()" < <  endl; }   
  4. };   
  5. template < class T> inline void swap( testClass< T>& x, 
    testClass
    < T>& y )   
  6. {   
  7. x.swap( y );   
  8. }   
  9. int main( void )  
  10. {   
  11. testClass< int> obj1;   
  12. testClass< int> obj2;   
  13. swap( obj1, obj2 );   

4. 類成員函式模板

  1. struct testClass  
  2. {   
  3. template < class T> void mfun( const T& t )  
  4. {   
  5. cout < <  t < <  endl;   
  6. }   
  7. template < class T> operator T()   
  8. {   
  9. return T();   
  10. }   
  11. };   
  12. int main( void )   
  13. {   
  14. testClass obj;   
  15. obj.mfun( 1 );   
  16. int i = obj;   
  17. cout < <  i < <  endl;   

5. 預設C++模板引數推導

  1. template < class T> struct test   
  2. {   
  3. T a;   
  4. };   
  5. template < class I, class O=test< I> > struct testClass   
  6. {   
  7. I b;   
  8. O c;   
  9. };   
  10. void main()  
  11. {  

6. 非型別C++模板引數

  1. template < class T, int n> struct testClass {   
  2. T _t;   
  3. testClass() : _t(n) {   
  4. }   
  5. };   
  6. int main( void ) {   
  7. testClass< int,1> obj1;   
  8. testClass< int,2> obj2;   

7. 空模板引數

  1. template < class T> struct testClass;   
  2. template < class T> bool operator==( const testClass< T>&, 
    const testClass
    < T>& )   
  3. {   
  4. return false;   
  5. };   
  6. template < class T> struct testClass   
  7. {   
  8. friend bool operator== < >
    ( const testClass&, const testClass& );   
  9. };   
  10. void main()  
  11. {  

8. template template 類

  1. struct Widget1   
  2. {   
  3. template< typename T>   
  4. T foo(){}   
  5. };   
  6. template< template< class T>class X>   
  7. struct Widget2  
  8. {   
  9. };   
  10. void main()  
  11. {  
  12. cout< <  3 < <  '\n';  

以上就是對C++模板的一些常用方法的介紹。


3,typedef

http://www.cnblogs.com/SweetDream/archive/2006/05/10/395921.html

C/C++語言中的typedef相信大家已經不陌生,本文對C/C++語言關鍵字typedef的各種用法作一個介紹。

typedef,顧名思義,為“型別定義”,可以解釋為:將一種資料型別定義為某一個識別符號,在程式中使用該識別符號來實現相應資料型別變數的定義。例如:

 

typedef unsigned int UINT;

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

{

    unsigned int a;   // it’s OK

    UINT b; // it’s OK, a and b are of the same type (int)

    // . . .    // code references the symbol a and b

    return 0;

}

 

上面的程式碼中,a和b屬於同一種資料型別(unsigned int型),因為UINT識別符號已經標示為unsigned int型別。上面的程式碼看似簡單,相信很多讀者都用過這種方法,但這絕不是typedef的全部,下面介紹使用typedef定義複雜資料型別的幾種用法。

 

1、 定義結構體型別

結構體是一種較為常見的資料型別,在C/C++程式設計中使用的非常廣泛。下面的程式碼就是結構體型別的一個應用:

#include <iostream.h>

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

{

    struct {int x; int y;} point_a, point_b;

    point_a.x = 10; point_a.y = 10;

    point_b.x = 0; point_b.y = 0;

    ios::sync_with_stdio();

    cout << point_a.x + point_a.y << endl;

    cout << point_b.x + point_b.y << endl;

    return 0;

}

上面的程式碼包含了兩個結構體變數:point_a和point_b,它們的資料型別相同,都是struct {int x; int y;}型別。這種說法可能有點彆扭,習慣上說point_a和point_b都是結構體型別,為什麼偏偏要說是struct {int x; int y;}型別呢?因為這種說法更加精確。比如在第一個例子中,對於“unsigned int a, b;”這條語句,我們可以說a和b都是整數型別,但更精確地說,它們應該是unsigned int型別。

既然struct {int x; int y;}是一種自定義的複雜資料型別,那麼如果我們要定義多個struct {int x; int y;}型別的變數,應該如何編寫程式碼呢?其實很簡單,就當struct {int x; int y;}是一個簡單資料型別就可以了:

struct {int x; int y;} var_1;   // 定義了變數var_1

struct {int x; int y;} array_1 [10];    // 定義了陣列array_1

struct {struct{int x; int y;} part1; int part2;} cplx;

上面的第三行定義了一個cplx變數,它的資料型別是一個複雜的結構體型別,有兩個成員:part1和part2。part1是struct {int x; int y;}型別的,part2是int型別的。

從上面的例子可以看出,如果在程式中需要多處定義struct {int x; int y;}型別的變數,就必須多次輸入“struct {int x; int y;}”這一型別名稱,況且,如果在結構體中有某個成員是struct {int x; int y;}型別的,還會使得定義變得非常繁雜而且容易出錯。為了輸入程式的方便,同時為了增強程式的可讀性,我們可以把struct {int x; int y;}這一資料型別定義為識別符號“Point”,那麼上面的程式就會變得更容易理解:

typedef struct {int x; int y;} Point;

Point var_1; // 定義了變數var_1

Point array_1 [10]; // 定義了陣列array_1

struct {Point part1; int part2;} cplx; // 定義了複雜型別變數cplx

需要說明的是,我們還可以使用下面的方法來定義結構體變數:

struct t_Point {

    int x; int y;};    // 注意,這裡最後一個分號不能省略

 

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

{

    struct t_Point a, b;

    // . . .

    return 0;

}

顯然,這種方法沒有typedef更加直觀(在C++中,main函式第一行的struct關鍵字可以省略,但在標準C中,省略該關鍵字會出現編譯錯誤)。

此外,對於定義連結佇列中的結點,我們可以這樣實現:

typedef struct t_node {

    int Value;

    struct t_node *next;

} Node;

當然也可以這樣定義:

typedef strcut t_node Node;

struct t_node {

    int Value;

    Node *next;

};

 

2、定義陣列型別

與定義結構體型別相似,可以使用typedef來定義陣列型別,例如:

typedef int MyIntArray [100];

那麼程式中的

MyIntArray ia;

就相當於

int ia[100];

3、 定義函式指標

看下面的程式碼:

typedef void (*FUNCADDR)(int)

此處FUNCADDR是指向這樣一個函式的指標,該函式的返回值為void型別,函式有一個int型的引數。再例如:

void print (int x)

{

    printf (“%d\n”, x);

}

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

{

    FUNCADDR pFunc;

    pFunc = print;  // 將指標指向print函式

    (*pFunc)(25);       // 呼叫函式print

    return 0;

}

函式指標一般用於回撥函式、中斷處理過程的宣告,以及在物件導向程式設計中對事件處理過程的宣告。

4、 定義類型別

類是物件導向程式設計語言中引入的一種新的資料型別,既然是資料型別,就可以使用typedef對其進行定義:

typedef class {

    private:

        int a;

    public:

        int b;

} MyClass;

其實這和定義結構體型別非常相似,不過很少有人這麼使用。


相關文章