程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> Effective C++ 第二版 1)const和inline 2)iostream

Effective C++ 第二版 1)const和inline 2)iostream

編輯:C++入門知識

條款1 盡量用const和inline而不用#define

>"盡量用編譯器而不用預處理"
Ex. #define ASPECT_R 1.653    編譯器永遠不會看到ASPECT_R這個符號名, 在源碼進入編譯器之前, 就被預處理程序去掉, ASPECT_R 不會被加入到符號列表中; 編譯報錯時, 報錯信息指向1.653, 讓程序員無法跟蹤錯誤;(這個問題也會出現在符號調試器中);

>Solution: 定義常量 const double ASPECT_R = 1.653; 常量定義一般是在頭文件中, 許多源文件會包含它; [me: 如果只是局部使用的常量應該放在cpp中]
Note 定義指針常量時要注意, 除了指針所指的類型定義成const, 指針也經常要定義成const; Ex. const char* const kName = "Scott";

定義類的常量, 把常量限制在類中, 為了保證常量只有一份拷貝, 把它定義為靜態成員:

123456 class GamePlayer {private:    static const int NUM_TURNS = 5; // constant declaration (老的編譯器不接受靜態成員聲明時初始化)    int scores[NUM_TURNS]; // use of constant...};

Note 如果上面只是NU_TURNS的聲明(沒有 '= 5'), 必須在類實現代碼中定義類的靜態成員: const int GamePlayer::NUM_TURNS = 5; // mandatory definition; goes in class impl. file;

[文中可能是寫反了, 頭文件中有了 '= 5'就已經是定義了, 不需要在cpp中再定義;]


Note 類內只允許初始化整數類型的靜態成員: int, bool, char...

Issue 必須在頭文件中定義靜態成員的情況: 當你的類需要用到這個類的常量時: e.g. GamePlayer::scores數組聲明(編譯時需要知道數組大小); [SIZE必須是靜態常量或枚舉數]

Solution 對於不支持頭文件定義靜態常量的編譯器, 借用enum, 當需要int類型時可以使用枚舉類型:


1234567 class GamePlayer {private:    enum { NUM_TURNS = 5 }; // "the enum hack" — makes    // NUM_TURNS a symbolic name for 5    int scores[NUM_TURNS]; //fine...}

#define 指令實現看起來像函數的宏, 但是不會導致函數的調用;


#define max(a,b) ((a) > (b) ? (a) : (b)) 要保證每個參數加上括號, 即使這樣還是會有預期外的情況:

123 int a = 5, b = 0;max(++a, b); // a 的值增加了2 次max(++a, b+10); // a 的值只增加了1 次

>根據值來決定max的運行;


使用內聯函數替代: inline int max(int a, int b) { return a > b ? a : b; }

使用模板來擴展int之外的類型:

123 template<class T>inline const T& max(const T& a, const T& b){ return a > b ? a : b; }

>模板產生一套函數, 每個函數比較兩個可以轉換成同種類型的對象, 返回大的;


Note 在使用模板寫max之類的通用函數前, 先檢查標准庫中是否已經存在;


const和inline減少了預處理的使用, 但是#include還不能缺少, #ifdef/#ifndef 在控制編譯的過程中也很重要;

 


條款2 盡量用<iostream>而不用<stdio.h>

scanf/printf 輕巧, 高效, 但不是類型安全的, 沒有擴展性; 需要把讀寫的變量和控制讀寫格式的信息分開(FORTRAN style);

>>和<<, 實現重載函數可以處理不同的類型; 讀寫語法形式相同, 不需要記住格式規定;

12345678910111213141516 int i;Rational r; //有理數cin >> i >> r;cout << i << r;class Rational {public:    Rational(int numerator = 0, int denominator = 1);...private:    int n, d; // 分子,分母    friend ostream& operator<<(ostream& s, const Rational& r);};ostream& operator<<(ostream& s, const Rational& r){    s << r.n << '/' << r.d;    return s;}

>"opertaor<<"不是成員函數(是操作符);


相對不足:

1) 有些iostream的操作比起相應的C stream效率低;

2) 標准化過程中, iostream庫在底層做了很多修改, 對要求最大可移植性的程序來說, 不同的廠商遵循標准的程度不同;


3) iostream庫的類有構造函數, <stdio.h>裡的函數沒有, 在某些涉及靜態對象初始化順序的時候, 如果可以確定沒有隱患, 用標准C庫更簡單實用;

優點: iostream庫的類和函數類型安全, 可擴展性好;

庫的包含: <iostream>

#include <iostream.h> 得到的是置於全局空間的iostream庫元素;

#include <iostream> 得到的是置於名字空間std下的iostream庫元素;

全局空間獲取元素可能導致名字沖突;

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved