類的資料類型指的是:類是成員變數和過程的彙總體,通過該彙總體,類得以完成將對象進行建模的任務
物件導向編程中最富挑戰性和創造性的工作就是類的設計,同時,面行對象編程也是以類的設計為基礎的
物件導向設計和物件導向編程的另外一個重要內容是關係:類與類之間,對象與對象之間
在return語句中,傳回值i:
傳值返回:將i先拷貝的臨時儲存空間,調用著獲得的是i的一個副本
引用返回:將i的值直接拷貝到接受的空間中(調用者)
使用引用返回的一個好處是:如果一個函數以引用返回,則這個函數調用可出現在指派陳述式的左邊
因為使用引用返回的函數返回的是一個實際單元,必須保證函數返回時該單元仍然有效(不能是臨時變數)
int & f()
{
int i;
return i;
} //錯誤
但是:
int f()
{
int i;
return i;
} //正確
關鍵字inline在函數生命中用來請求將該函數以內聯方式展開,也就是說,在每個調用該函數的地方插入該函數的實現代碼
這個特定和宏很類似。避免了開銷。但是如果函數很大,或者使用在很多地方,程式的可執行代碼變得很大
與宏不同的是,內嵌函式是通過編譯器完成的。要考慮語義(宏不檢查語義)
所有沒有預設的參數都放在參數開始部分,接下來是具有預設值的參數,穿插著不行!!
重載:能通過參數個數和類型區別
C++中加extern c{} 的原因是為了屏蔽他們在編譯中產生的符號的差別
void (double,int)和 void (int,double) 是重載函數
但是傳回值不一樣不是重載函數 :int s(int) 和 double s(int)
C++中struct 傳遞是按值傳遞:
看下面一個例子:
結果:
為了驗證結果,同時和引用傳遞對比,下面修改一下:
修改後結果:
那下面這種情況:
結果是不是意料之中:
先看看下面的情況再說 :
來看結果:
總結一下:
在C++中,結構體是以傳值的方式進行的,通過例子1和例子2我們可以看出來,同樣,雖然例子3和例子4達到的結果相同,但是同時也從側面支援了我們研究結果的正確性
例子3是結構體傳遞,但是它的變數確實沒變,之所以最終的值發生了變化,是因為結構體的變數的指向的值發生了變化。
也說明了引用是最保險的辦法
函數重載和預設變數結合在一起的時候小心一點:
看下面例子有錯沒有:
結果:
知道了吧,如果這樣重載的話,編譯器找不到你要調用的函數,不知道你要調用哪一個 ?就想兩個人都叫寧華,一個男的,一個女的。他們兩個明顯屬於不同的個體,但是如果你不加細分處理的話,僅僅是叫寧華,他們會不知道叫的是誰,當然其他人也不知道,所以我們應該從其他地方區分,例如,叫女寧華,就一女的,叫男的,就男的。這不是說寧華是兩性的,也不是說她會變性,只是區分兩個不同的個體而已
大家對C語言的鏈表已經熟悉的一聽說到華仔就知道是女的,一聽說小雌就知道是男的一樣。那麼C++的鏈表呢?
雖然本質沒有什麼差別,但是還是熟悉一下吧,另外熟悉一下C++記憶體配置問題,下面一個例子代過:
^_^,哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈^_^
下面讓我們來看看,像王小賤一樣賤的知識點:例外處理
這一塊比較簡單,條條框框套進去,然後正常編程就行。一個例子搞定:
C++支援無名聯合,即沒有名字的聯合,這裡我們介紹一下,同時要注意聯合的特性:通過例子說明:
結果:
對比一下下面這個特別是結果:
結果:
大家一定會發現:為什麼給兩個變數賦值順序不同顯示的不同,這個不解釋:常識!
無名聯合的成員可以當作普通變數使用。
在相同的範圍之內,不能定義與無名聯合中的成員同名的變數。
並且::不無定義以無名聯合為資料類型的變數!!
從一定程度上來說,無名聯合和{}更像!只是稍微變數範圍的區別。
下面再看一個支援觀點的例子:
看結果:
一目瞭然,不解釋,本質上面已經說的很清楚
大家對結構體已經很熟悉了吧!現在我們看看它另類一點的用法。此用法和小雌一樣雌!
下面這個例子的錯誤很常見,大家注意一下:
這個例子不再寫輸出了,也不注釋掉出錯的兩行,示範正確的了,大家仔細看看:
大家要注意一點:f_ptr已經不是指向float的指標,而是指向類C中的float成員。這樣限定是不是在安全上或者保護變數方面有很大好處
因為C++和C語言有絲絲區別,而且結構體裡面加上函數指標,我們用一個例子 來搞定它:
C++基礎知識就這些,下面看一下編程的常見錯誤:
1,區分using指令和using聲明:
using namespace + 命名空間 ==========> using 指令
using + 命名空間::命名空間內元素 ==========> using 聲明
2,在使用標準輸入/輸出流進行任何鍵盤輸入和視頻輸出之前,必須包含:
#include <iostream>
為了使用特性,通常這樣:
#include <iostream>
using namespace std;
3,using namespace std 和 iostream.h 等*.h不能共存。如果是舊版本,就用*.h,不能混用,否則出現錯誤
4,<<和>>只能輸出一個資料,或者輸入一個資料,如果想多個,每個後面前面都要有<<或者>>
5,操作符<<的優先順序比較關係、比較、邏輯和賦值操作符高,因此
cout << n < m << endl;
是錯誤的,應該這樣:
cout << (n < m) << endl;
6,要是用帶參數的操作符,必須包含標頭檔iomanip.
7,操作器作用於資料流之中,除了控制域寬的操作器(控制域寬的操作器在輸出了一個字串或數字後自動清0)之外,其他所有操作器所造成的影響具有持久性。不要誤認為在語句結束後所有輸入輸出設定都恢複為預設值
8,混用C和C++的輸入/輸出功能,可能會導致不可預測的錯誤,使用函數:
ios::sync_with_stdio()
可以消除這種隱患
先看這種:
這樣做是很危險的,下面的是安全的:
9,檔案操組,必須包含標頭檔fstream
10,強制類型轉換放在需要轉換的資料類型包含在<>而不是圓括弧內:
static_cast(int)(26) //ERROR
static_cast(int)<26) //ERROR
static_cast(<int><26> //ERROR
static_cast<int>(26) //RIGHT
<>內是被最終要被轉化成的資料類型
C++有四種資料類型轉換:
static_cast<>()把一種資料類型轉換成另一種資料類型
const_cast<>()把資料類型的常量性去掉
reinterpret_cast<>(),用來改變指標類型,謹慎用
dynamic_cast<>()用於繼承層次中的類型轉換
11,C++允許變數隨時使用,隨時定義。但是作用於的範圍顯得非常亂,一定要注意:
特別是for迴圈中的定義的臨時變數,只在for迴圈中有效
12,與檔案操作相關的open()函數接受C風格的的字串
string s = "myfile.dat";
ifstream infile;
infile.open(s);
是錯誤的,應該為:
ifstream infile;
infile.open("myfile.dat");
或者:
string s=“myfile.dat";
ifstream infile;
infile.open(s.c_str());
12,當用操作符<<將字串讀入string類型字串時,遇見空格就結束了!要想讀入一行用getline()
13,賦值操作符可用於string類型。操作符右邊可以是string字串、C風格字串或字元。但左邊必須是string字串:
同理 += 操作符也一樣。左邊只能是string字串,右邊可以是string字串,C風格的字串、或是一個字元
+操作符也一樣,但是還要注意一點,+ 操作符的右邊的兩個不能都是字串。但是可以都是string字串,可以一個C字串、一個string或者一個string、一個字元
string s1 ,s2 = "W.C.",s3 = "Fields";
s1 = s2 + s3; //OK
s1 = s2 + "Fileds"; //OK
s1 = "W" + s3; //OK
s1 = "W.C." + "Fields"; //ERROR
14,對於string類型的下述函數:erase、insert、replace和substr等,傳給它們的第一個參數不能大於或等於字串的長度。
超出長度範圍的錯誤長度將導致程式異常終止,儘管通過例外處理可以捕捉到這些錯誤
15,調用未聲明的函數是非法的。每個系統函數也必須線聲明,通常是包含相應的標準標頭檔
16,不為函數指定傳回值是錯誤的
17,main函數的下面兩種定義是可移植的:
int main(){}
int main(int argc,char * argv[])
18,因為採用引用返回方式的函數返回的是實際的單元,所以必須保證該單元在函數返回後依然存在
19,關鍵字inline用於函式宣告而不是函數定義:
下面程式是錯誤的:
需要修改如下代碼,下面的代碼是正確的:
因為內斂函數swap只在它定義的地方到檔案結束才可見,所以它對main來說是不可見的,因此編譯器將告之找不到swap函數
20,預設參數應在函式宣告而非函數定義中給出:
下面的代碼是錯誤的:
看看哪出錯了,出的什麼錯誤:
看吧,不認識它,應該這樣來寫:
21,對於使用動態方式分配的對象,在該對象超出其範圍之前不使用delete將其刪除,是一種不良的編程習慣:就是在一個作用於中動態申請,在另一個範圍中刪除(不一定)