C和C++指針的最重要的區別在於:C++是一種類型要求更強的語言。就void *
而言,這一點表現得更加突出。C雖然不容許隨便地把一個類型的指針指派給另外一個類型,但容許經過void *
來實現。例如:ios
bird* b; rock* r; void* v; v = r; b = v;
C++不容許這樣作,其編譯器將會給出一個出錯信息。若是真的想這樣作,必須顯式地使用映射,通知編譯器和讀者。程序員
參數傳遞準則
當給函數傳遞參數時,人們習慣上應該是經過常量引用來傳遞,這種簡單習慣能夠大大提升效率:傳值方式須要調用構造函數和析構函數,然而若是不想改變參數,則可經過常量引用傳遞,它僅須要將地址壓棧。 事實上,只有一種狀況不適合用傳遞地址方式,這就是當傳值是惟一安全的途徑,不然將會破壞對象(而不是修改外部對象,這不是調用者一般指望的)。安全
C++訪問權限控制:public、private、protected
其中protected只有在繼承中才有不一樣含義,不然與private相同,也就是說二者只有一點不一樣:繼承的結構能夠訪問protected成員,但不能訪問private成員。函數
前置聲明注意工具
struct X; // Declaration(incomplete type spec) struct Y { void f(X *memx); void g(X memx); // not allowed, the size of X is unknown. };
這裏f(X*)引用了一個X對象的地址,這是沒有任何問題的,但若是是void g(X memx);
就不行了,編譯器會報錯。這一點很關鍵,由於編譯器知道如何傳遞一個地址,這一地址大小是必定的,而不用管被傳遞的對象類型大小。若是試圖傳遞整個對象,編譯器就必須知道X的所有定義以肯定它的大小以及如何傳遞它,這就使程序員沒法聲明一個相似於Y :: g(X) 的函數。優化
C++是純的嗎?
若是某個類的一個函數被聲明爲friend
,就意味着它不是這個類的成員函數,但卻能夠修改類的私有成員, 並且它必須被列在類的定義中,所以咱們能夠認爲它是一個特權函數。這種類的定義提供了有關權限的信息,咱們能夠知道哪些函數能夠改變類的私有部分。 所以,C++不是徹底的面嚮對象語言,它只是一個混合產品。friend
關鍵字就是用來解決部分的突發問題。它也說明了這種語言是不純的。畢竟C + +語言的設計是爲了實用,而不是追求理想的抽象。this
C++輸入輸出流的操縱算子(manipulator)有:endl、flush、ws、hex等。spa
cout<<flush; // 清空流 cout << hex << "0x" << i; // 輸出16進制 cin>>ws; // 跳過空格
iostream.h還包括如下的操縱算子:設計
如何創建咱們本身的操縱算子?
咱們可能想創建本身的操縱算子,這是至關簡單的。一個像endl這樣的不帶參數的操縱算子只是一個函數,這個函數把一個ostream引用做爲它的參數。對endl的聲明是:指針
ostream& endl(ostream&);
例子:產生一個換行而不刷新這個流。人們認爲nl比使用endl要好,由於後者老是清空輸出流,這可能引發執行故障。
ostream& nl(ostream& os) { return os << "\n"; } int main() { cout << "newlines" << nl << "between" << nl << "each" << nl << "word" << nl; return 0; }
C語言中const與C++中const的區別:
常量引進是在早期的C++版本中,當時標準C規範正在制訂。那時,常量被看做是一個好的思想而被包含在C中。可是,C中的const意思是「一個不能被改變的普通變量」,在C中,它老是佔用存儲並且它的名字是全局符。C編譯器不能把const當作一個編譯期間的常量。在C中, 若是寫:
const bufsize=100; char buf[bufsize];
儘管看起來好像作了一件合理的事,但這將獲得一個錯誤結果。由於bufsize佔用存儲的某個地方,因此C編譯器不知道它在編譯時的值。在C語言中能夠選擇這樣書寫:
const bufsize;
這樣寫在C++中是不對的,而C編譯器則把它做爲一個聲明,這個聲明指明在別的地方有存儲分配。由於C默認const是外部鏈接的,C++默認cosnt是內部鏈接的,這樣,若是在C++中想完成與C中一樣的事情,必須用extern把鏈接改爲外部鏈接:
extern const bufsize;//declaration only
這種方法也可用在C語言中。
注意:在C語言中使用限定符const不是頗有用,即便是在常數表達式裏(必須在編譯期間被求出);想使用一個已命名的值,使用const也不是頗有用的。C迫使程序員在預處理器裏使用#define。
類裏的const和enum
下面的寫法有什麼問題嗎?:
class bob { const size = 100; // illegal int array[size]; // illegal }
結果固然是編譯不經過。why?由於const在類對象裏進行了存儲空間分配,編譯器不能知道const的內容是什麼,因此不能把它用做編譯期間的常量。這意味着對於類裏的常數表達式來講,const就像它在C中同樣沒有做用。
在類裏的const意思是「在這個特定對象的壽命期內,而不是對於整個類來講,這個值是不變的」。那麼怎樣創建一個能夠用在常數表達式裏的類常量呢?
一個普通的辦法是使用一個不帶實例的無標記的enum。枚舉的全部值必須在編譯時創建,它對類來講是局部的,但常數表達式能獲得它的值,這樣,咱們通常會看到:
class bob { enum { size = 100 }; // legal int array[size]; // legal }
使用enum是不會佔用對象中的存儲空間的,枚舉常量在編譯時被所有求值。咱們也能夠明確地創建枚舉常量的值:enum { one=1,two=2,three};
類裏面的const成員函數
class X { int i; public: int f() const; }
這裏f()是const成員函數,表示只能const類對象調用這個函數(const對象不能調用非const成員函數),若是咱們改變對象中的任何一個成員或調用一個非const成員函數,編譯器將發出一個出錯信息。
關鍵字const必須用一樣的方式重複出如今定義裏,不然編譯器把它當作一個不一樣的函數:
int X::f() const { return i;}
任何不修改爲員數據的函數應該聲明爲const函數,這樣它能夠由const對象使用。
注意:構造函數和析構函數都不是const成員函數,由於它們在初始化和清理時,老是對對象做些修改。
若是咱們想要創建一個const成員函數,但仍然想在對象裏改變某些數據,這時該怎麼辦呢?這關係到按位const和按成員const的區別。按位const意思是對象中的每一個位是固定的,因此對象的每一個位映像從不改變。按成員const意思是,雖然整個對象從概念上講是不變的,可是某個成員可能有變化。當編譯器被告知一個對象是const對象時,它將保護這個對象。
這裏咱們要介紹在const成員函數裏改變數據成員的兩種方法。
第一種方法已成爲過去,稱爲「強制轉換const」。它以至關奇怪的方式執行。取this(這個關鍵字產生當前對象的地址)並把它強制轉換成指向當前類型對象的指針。看來this已是咱們所需的指針,但它是一個const指針,因此,還應把它強制轉換成一個普通指針,這樣就能夠在運算中去掉常量性。下面是一個例子:
class Y { int i, j; public: Y() { i = j = 0; } void f() const; }; void Y::f() const { //! i++; // error ((Y*)this)->j++; // ok , cast away const feature. }
這種方法可行,在過去的程序代碼裏能夠看到這種用法,但這不是首選的技術。問題是:this沒有用const修飾,這在一個對象的成員函數裏被隱藏,這樣,若是用戶不能見到源代碼(並找到用這種方法的地方),就不知道發生了什麼。
第二種方法也是推薦的方法,就是在類聲明裏使用關鍵字mutable
,以指定一個特定的數據成員能夠在一個const對象裏被改變。
class Y { int i; mutable int j; public: Y() { i = j = 0; } void f() const; }; void Y::f() const { //! i++; // error ((Y*)this)->j++; // ok , mutable. }
volatile的語法與const是同樣的,可是volatile的意思是「在編譯器認識的範圍外,這個數據能夠被改變」。不知何故,環境正在改變數據(可能經過多任務處理),因此,volatile告訴編譯器不要擅自作出有關數據的任何假定—在優化期間這是特別重要的。若是編譯器說:「我已經把數據讀進寄存器,並且再沒有與寄存器接觸」。通常狀況下,它不須要再讀這個數據。可是,若是數據是volatile修飾的,編譯器不能做出這樣的假定,由於可能被其餘進程改變了, 它必須重讀這個數據而不是優化這個代碼。
注意:
- 就像創建const對象同樣,程序員也能夠創建volatile對象,甚至還能夠創建const volatile對 象,這個對象不能被程序員改變,但可經過外面的工具改變。
- 就像const同樣,咱們能夠對數據成員、成員函數和對象自己使用volatile,能夠而且也只能爲volatile對象調用volatile成員函數。
- volatile的語法與const是同樣的,因此常常把它們倆放在一塊兒討論。爲表示能夠選擇兩個中的任何一個,它們倆通稱爲c-v限定詞。