1、存儲類
4個存儲類說明符:auto、register、extern、static。標識符的存儲類說明符可以確定其存儲類、范圍和連接。
分兩類:
自動存儲類——auto和register。
只有變量能作為自動存儲類,函數的局部變量和參數通常都是自動存儲類。局部變量默認為自動存儲類。
靜態存儲類——extern和static。
這兩個關鍵字用來聲明靜態存儲類變量和函數的標識符。這種變量從程序開始執行時就存在。對于變量,程序開始執行時就分配和初始化存儲空間;對于函數,從程序開始執行時就存在函數名。
全局變量和函數名默認為extern。用static聲明的局部變量仍然只在定義該變量的函數中使用,但與自動存儲類變量不同的是,static局
部變量在函數退出時保持其數值。下次調用這個函數時,static局部變量包含上次函數退出時的值。注:所有靜態存儲類的數字變量都默認初始化為0。
全局變量能夠被同一個文件中該變量聲明后的所有函數訪問。其他文件中的函數也可以訪問全局變量,但必須在使用前予以聲明,如在一個文件中定義:
int flag;
則在另一個文件中需定義如下:
extern int flag;
才可使用全局變量flag。
說明:存儲類別說明符extern告訴編譯器:變量flag或者稍后定義在同一個文件中,或者在另一個文件中定義。而編譯器不知道flag定義在何
處,因此讓連接程序查找flag,如果沒有找到flag的定義,則發出錯誤消息,如找到,則指明其位置,從而解決對該變量的引用。對于函數的引用也是如
此。可以用static關鍵字來防止定義在其他文件中的函數(沒有在同一個文件中定義)使用這些全局變量或函數。
2、enum的聲明
enum Status(CONTINUE,WON,LOST);
Status gameStatus;
默認枚舉常量(CONTINUE,WON,LOST)從0開始,增量為1。
enum Months(JAN=1,FEB,MAR,APR,MAY,JUN,JUL,AUG,SEP,OCT,NOV,DEC);
也可指定從某個常數開始,如上例從1開始,增量為1。
3、默認參數
必須是函數參數表中最右邊的參數。
int fun1(int,int=1,int=2); //正確
int fun2(int=1,int); //錯誤
默認參數應在函數名第一次出現是指定,通常在函數原型中。
4、一元作用域運算符 :: 可以在同名局部變量的作用域中訪問全局變量。
5、函數重載
通過函數簽名(函數名和參數類型的組合,包括參數個數,類型,順序)來區別。編譯器用參數個數和類型為每個重載函數編碼(名字改編或名字修飾)。
6、數組
如果初始化的元素比數組中的元素少,則其余元素自動初始化為0。所以至少需要初始化第一個元素,才能將其余元素自動初始化為0。但是,如果聲明為static數組,則在沒有顯式初始化時,便以其將自動初始化為0。
數組維數只能用常量聲明,無論是靜態數組還是自動數組。
字符數組可以用字符串直接量(注:字符串直接量返回指向第一個字符的指針)初始化。
char string1[ ]= " first " ;
字符串 " first " 包含五個字符加一個特殊字符串終止符 ' \0 ' 。故string1的長度為6。
將數組傳遞給函數:
原型:
void modifyArray(int[ ] , int );
或
void modigyArray(int anyArrayName[ ], int anyVariableName);
C++編譯器將忽略原型中的變量名,上述兩種原型聲明等價。
7、指針
int a;
int *aPtr = &a ;
則&*aPtr和*&aPtr將返回相同的值,即為aPtr的值,可知&和*運算符是互逆的。
聲明為const的指針應在聲明時初始化(如果是函數參數,則用傳入函數的指針初始化)。
結構(類)總是按值調用,傳遞整個結構(類)的副本。
數組總是按引用調用,數組名就是數組第一個元素的地址。
sizeof運算符作用于數組名時,返回數組總共占用的字節數。
double realArray[22];
sizeof realArray /sizeof(double); //返回22
char* suit[4]={" Hearts ", " Diamonds ", " Clubs ", " spades "};
suit中的數組元素存放每個字符串的首字母的地址,因此suit是定長的。
所以sizeof suit將返回16(如果單個地址占用4字節)。
8、函數指針
函數指針包含函數在內存中的地址。
將函數指針傳給函數:
原型:
void bubble( int[ ], const int, int ( * ) ( int, int ) );
上述第三個參數即為函數指針類型。
看函數定義:
void bubble( int work[ ], const int size, int ( * compare ) ( int, int ) )
{
( * compare) ( a, b); //a,b為兩個int型的參數
或者
compare( a, b); //a,b為兩個int型的參數
}
推薦使用第一種形式,因它顯示說明compare為函數指針,第二種形式容易認為compare是個實際函數。
函數指針數組聲明如下:
void ( * f[ 3 ] )( int )={function1,function2,function3};
上式聲明具3個函數指針的數組f。
函數調用如下:
(* f[0])(a); //a為int型參數
9、構造函數與析構函數
一般情況下,析構函數的調用順序與構造函數相反。
全局范圍中定義的對象的構造函數在文件中的任何其他函數(包括main)執行之前調用(但不同文件之間全局對象構造函數的執行順序是不確定的)。當main終止或者調用exit函數時調用相應的析構函數。
當程序執行到對象定義時,調用自動局部對象的構造函數。該對象的析構函數在對象離開范圍時調用(即離開定義對象的塊時)。自動對象的構造函數和析構函數在每次對象進入和離開范圍時調用。
static局部對象的構造函數旨在程序執行首次到達對象定義時調用一次,對應的析構函數在main終止或調用exit函數時調用。
可見構造函數調用順序:
全局對象-〉局部自動(或靜態)對象(按執行順序)。
析構函數調用順序:
局部自動對象-〉main( )執行結束后,靜態對象(局部或全局)-〉全局對象。
10、關于成員函數返回引用
不要讓類的public成員函數返回對該類private數據成員的非const引用(或指針),返回這種引用會破壞封裝。
如:
#include<iostream>
using namespace std;
class Time
{
public:
int getHour();
int &badSetHour(int);
private:
int hour;
int minute;
int second;
};
int Time::getHour()
{
return hour;
}
int &Time::badSetHour(int hh)
{
hour=(hh >= 0 && hh < 24 ) ? hh : 0;
return hour;
}
int main()
{
Time t;
int &hourRef=t.badSetHour(20);
cout<<hourRef<<endl;
hourRef=8;
cout<<t.getHour()<<endl;
t.badSetHour(12) = 5;
cout<<t.getHour()<<endl;
return 0;
}
輸出為:
20
8
5