1.3 C++對C的擴充
1.3.1 C++的輸入輸出
1. 標準輸入輸出流cout和cin。在頭文件<iostream>。
2. cerr:標準出錯輸出
clog:cerr的緩衝形式
3. cin>>:>>常稱爲“提取運算符”。用”>>” 從鍵盤取得數據並送到輸入流cin中,然後再送到內存。
4. 簡單的程序:
int mian(){
cout<<”Please enter your name : ”<<endl;
char name[20];
cin>>name;
cout<<”Hello,”<<name<<endl;
return 0;
}
注意:程序中對變量的定義放在了執行語句後面,在C中是不允許的。
C++允許對變量的聲明放在程序的任何位置,但必須在使用變量之前。
1.3.2 用const定義常變量
1. 在C中,常用#define指令定義符號常量,如: #define PI 3.14159
實際上,只是在預編譯時進行字符置換,把程序中出現的字符串PI 全部置換成3.14159。
預編譯之後,程序中就沒有PI這個標識符了。
注意:PI不是變量,沒有類型,不佔用存儲空間。
2. 看簡單程序:
int a=1,b=2;
#define PI 3.14159
#define R a+b
cout<<PI*R*R<<endl;
輸出的並不是3.14159*(a+b)*(a+b),而是3.14159*a+b*a+b,程序因此常常會出錯。
C++提供了用const定義常變量的方法,如: const float PI 3.14159
注意:PI具有變量的屬性,有數據類型,佔用存儲空間,有地址,可以用指針指向它,知識在程序運行期間值是固定的,不能改變。
1.3.3 函數原型聲明
1. C中,以下三種聲明方式都能通過編譯:
int max(int x,int y);
int max();
max();
在C++中,如果函數調用的位置在函數定義之前,則必須進行函數原型聲明,使編譯系統嚴格檢查。
int max(int x,int y);
int max(int,int);
注意:在編譯時,只檢查參數類型,而不檢查參數名。
1.3.4 函數的重載
1. 在C中,規定在同一作用域(例如同一文件模板中),不能有同名的函數
C++ 允許在同一作用域中用同一函數名定義多個函數,但是,函數的參數個數和參數類型不相同。
2. 簡單程序:
int max(int a,int b, int c){
if(b>a) a=b;
if(c>a) a=c;
return a;
}
float max(float a,float b, float c){
if(b>a) a=b;
if(c>a) a=c;
return a;
}
int main(){
int a,b,c;
float d,e,f;
cin>>a>>b>>c;
cin>>d>>e>>f;
int m;
m=max(a,b,c);
cout<<”max_i=”<<m<<endl;
float n;
n=max(d,e,f);
cout<<”max_f=”<<n<<endl;
}
系統會根據實參的類型找到與之匹配的函數,然後調用該函數。
1.3.5 函數模板
1. 簡單程序:
template<typename T>
T max(T a,T b,T c){
if(b>a) a=b;
if(c>a) a=c;
return a;
}
int main(){
int i1=8,i2=5,i3=6,i;
double d1=56.9,d2=90.765,d3=43.1,d;
i=max(i1,i2,i3);
d=max(d1,d2,d3);
cout<<”i_max=”<<i<<endl;
cout<<”d_max=”<<d<<endl;
}
通用函數定義:
template<class T>
template<typename T>
注意: 它只適用於函數的參數個數相同而類型不同,且函數體相同的情況,如果參數個數不同,則不能用函數模板。
1.3.6 有默認參數的函數
1. float volume(float h,float r=12.5)
實參與形參的結合是從左至右順序進行的,因此指定默認值的參數必須放在形參表中的最右端,否則出錯。
注意:
1. 如果在函數調用前需要函數聲明,此時必須在函數聲明中給出默認值,在函數定義時可以不給出默認值。也就是在調用之前將默認值的信息通知編譯系統。由於編譯是從上到下逐行進行的,如果在函數調用之前未得到默認值的信息,則編譯到函數調用時,會認爲實參個數與形參個數不匹配而報錯。
2. 一個函數既不能作爲重載函數,又作爲有默認參數的函數,會出現二義性。
1.3.7 變量的引用
1. int a;
int &b=a;
這就聲明瞭b是a的引用,即a的別名。
注意:
1. 對變量聲明一個引用,並不另開闢內存單元,b和a都代表同一變量單元,因此在 建立引用時只有聲明,沒有定義。
2. 在聲明一個引用時,必須同時使之初始化,不能再作爲其他變量的引用。
3. 區分是聲明引用還是取地址操作:
當&a的前面有類型符時(int &a),必然是引用,如(p=&a)此時是取地址操作。
4. int a=3;
int &b=a;
int &c=b;
此時,整型變量a有兩個別名,b和c。
5. 不能建立void類型的引用
因爲任何存在的變量都是非void類型。
6. 不能建立引用的數組
char c[6]=”hello”;
char &rc[6]=c;
數組名c只代表數組首元素的地址,本身並不是一個佔有存儲空間的變量。
7. 可以用const對引用加以限定
int i=5;
const int &a=i;
a=3; //錯誤
i=3; //合法
並不阻止改變引用所代表的變量的值。
8. int i=5;
const &a=i+3; //合法
此時編譯系統這樣處理:生成一個臨時變量存放表達式的值,引用是該臨時變量的別名,如下:
int temp=i+3;
const int &a=temp;
臨時變量是內部實現的,用戶不能訪問。
2. C++ 添加引用主要是利用它作爲函數參數,擴充函數傳遞數據的功能。
在C中,函數參數傳遞有以下兩種情況:
1. 將變量名作爲實參(形參和實參不是同一存儲單元)
2. 傳遞變量的指針
在C++中,傳送變量的別名。實際上,實參傳給形參的是實參的地址。
3. 使用引用和指針變量作爲形參的不同:
設立指針變量需要另開闢內存單元,而引用不是獨立的變量,不單獨佔內存單元。
1.3.8 內置函數
調用函數需要時間,如果有些函數頻繁調用,會降低程序執行效率。
C++提供內置函數(也叫內聯函數,內嵌函數)。即在編譯時將所調用的函數的代碼嵌入到主調函數中。
inline int max(int a ,int b,int c)
注意:只有對於規模小且頻繁使用的函數,纔可以大大提高運行效率。
1.3.9 作用域運算符
先看程序:
float a=13.5
int main(){
int a=5;
cout<<a;
return 0;
}
輸出5;
如果想輸出全局變量,C++提供作用域運算符“::”。
程序改爲:
int main(){
int a=5;
cout<<a<<endl;
cout<<::a<<endl;
return 0;
}
“::a”表示全局作用域中的變量。注意:“::”不能訪問函數中的局部變量。
1.3.10 字符串變量
1. 字符數組處理字符串外,C++提供了字符串類型定義字符串變量。
string不是C++具有的基本類型(char,int,float,double),它是在標準庫中的一個字符串類。
#include<string>
2. char str[10];
str=”Hello”; //錯誤
string word = ”Canada”; //在定義字符串變量時,不必指定長度
word[2] = ‘m’; //修改後位“Camada”
3. 定義字符串數組(區別於字符數組)
string name[3]={“zhang”,”li”,”wang”};
說明:每個字符串元素中只包含字符串本身的字符不包括“\0”。
疑問:字符串數組中每個元素的長度不同,定義時怎麼給數組分配存儲空間的呢?
解答:實際上,編譯系統爲每個字符串分配固定的字節數(4個字節),在這個存儲單元中,並不是直接存放字符串本身,而是存放字符串的地址。name[0]存放的是“zhang”的首地址。
1.3.11 動態分配/撤銷內存的運算符new和delete
1. 在C語言中,利用malloc和free分配和撤銷內存空間的。但是malloc必須指定開闢內存的大小。
在C++中,利用new和delete取代。
new 類型[初值]
delete p;
delete []pt;
注意:用new分配數組空間時不能制定初值。
2. 簡單程序:
struct student{
char name[10];
int num;
};
int main(){
student *p;
p=new student;
strcp(p->name,”wang”);
.......
}
說明:
定義一個指向結構體的指針p。用new開闢空間存放一個student類型的變量。執行new後返回一個指向student的指針存放在p中。
如果內存不足,new會返回一個NULL。
new和delete是運算符,不是函數,因此執行效率高。
1.4 C++程序的編寫和實現
1. 編寫源程序(.cpp)
2. 對源程序進行編譯(生成.obj文件)
作用:對源程序進行詞法檢查和語法檢查,error和warning
3. 將目標文件進行連接(生成.exe可執行文件)
將.obj輸入內存,與系統提供的庫文件等連接。
4. 運行程序
5. 分析結果
2.2 類的聲明和對象的定義
1. 類是對象的抽象,而對象是類的具體實例。
2. 用struct聲明的類,如果對其成員既不指定private也不指定public,則系統默認認爲是公共的。
用class聲明的類,如果對其成員既不指定private也不指定public,則系統默認認爲是私有的。
3. 一個對象所佔的空間只取決於該對象中數據成員所佔的空間,而與成員函數無關。
函數的目標代碼是存儲在對象空間之外的,如果一個類定義了10個對象,這些對象的成員函數對應的是同一個成員函數代碼段。(this指針)
4. 如果在類體中定義的成員函數中不包括循環等控制結構,C++系統則會自動對它們作爲inline函數來處理。
5. 如果只聲明瞭類而未定義對象,則類的一般成員函數是不佔內存的,只有在定義了類對象時,才爲數據成員分配空間。