1、 函數設計的技巧
函數是由函數參數、返回值和函數體3個要素組成的。
1.1函數體設計的規則
·函數的功能要單一,不要設計多用途的函數
·函數體的規模要小,盡量控制在50行代碼以內
·盡量避免函數帶有“記憶”功能。相同的輸入應當產生相同的輸出。帶有“記憶”功能的函數,其行為可能是不可預測的,因為它的行為可能取決于某種“記憶狀態”
·要檢查輸入參數的有效性,還要檢查通過其他途徑進入函數體內的變量的有效性,例如全局變量、文件句柄等
·用于出錯處理的返回值一定要清楚,讓使用者不容易忽視或誤解錯誤情況
·使用斷言捕捉不應該發生的非法情況。不要混淆非法情況與錯誤情況之間的區別,后者是必然存在的并且是一定要作出處理的。
·在函數的入口處,使用斷言檢查參數的有效性(合法性)。
1.2參數的設計規則
·參數的書寫要完整
void SetValue(int width, int height);//良好的風格
void SetValue(int,int);//不良的風格

·如果參數是指針,且僅作為輸入用,則應在類型前加const,以防止它在函數體內被修改。
void StringCopy(char *strDestination, const char *strSource);
·如果輸入參數以值傳遞的方式傳遞對象,則宜改用“const &”方式來傳遞,這樣可以省去臨時對象的構造和析構過程,從而提高效率。傳遞引用實際上也會產生臨時的指針傳遞,只是在對象的拷貝需要消耗很多時間的時候,才會考慮傳遞引用。
·參數的個數應該控制在5個以內,不宜太多。
·盡量不要使用參數和類型不確定的參數,這種風格的函數在編譯時喪失了嚴格的類型安全檢查
1.3返回值的設計規則
·不要省略返回值的類型,如果沒有返回值,設置為返回void類型。
·不要將正常值和錯誤標志混在一起返回。正常值用輸出參數獲得,而錯誤標志用return語句返回
2、 宏定義的使用技巧
宏定義了一個代表特定內容的標識符。預處理程序會把源代碼中出現的宏標識符替換成宏定義時指定的值
2.1防止頭文件不被重復包含
#ifndefine _INCLUDER_HEADER_H_
#define _INCLUDER_HEADER_H_
#include *public.h
#endif
該段代碼的作用防止了public.h被工程重復包含
2.2定義代表某個值的全局符號
比如,用預處理指令#define聲明一個常數,用以表明一年中有多少秒
#define SECONDS_PER_YEAR (60*60*24*365)UL //定義帶參數的宏
寫一個宏,這個宏輸入兩個參數并返回較小的一個:
#define MIN(A,B) ((A)<=(B)?(A):(B))
2.3_DEBUG宏的運用技巧
_DEBUG是編譯器留給我們的預編譯屬性。如VC編譯器,對于每個工程都有Debug和Release兩種不同的模式。在Debug模型下面,_DEBUG會被編譯器自動定義,在Release模式下則不會。因此我們可以使一段程序產生不同的輸出,如:
…
#ifdef _DEBUG
cout<<”debug”<<endl;
#else
cout<<”release”<endl;
#endif
…
這在大型工程中是十分有用的,比如有一個程序要求用戶交互輸入50個數據,然后根據輸入計算出結果。如果調試時每次手動輸入50個數據是很辛苦的,也是容易出錯的,所以我們可以在調試的時候把數據指定好,而發行的時候顯示交互窗口,這樣做既不改變程序結構,又方便調試。
#ifdef _DEBUG
for(i=0;i<50;i++)
A[i]=i
#else
ShowInputWindow(A);
#endif
3、 const使用技巧
const是constant的縮寫,“恒定不變”的意思。被const修飾的東西都受到強制保護,可以預防意外的變動,能提高程序的健壯性。鑒于其有這么多優點,const關鍵字最常用的是用來定義常量。const更大的魅力是它可以修飾函數的參數、返回值和函數的定義體。
3.1 const常量的定義
常量是一種標識符,它的值在運行期間恒定不變,在上一節中,闡述#define定義的常量,稱為宏常量。那么利用const定義的常量稱為const常量。合理地利用常量可以提高程序的可讀性、易修改性等。
3.2 const常量的定義技巧
·盡量用含義直觀的常量來表示那些將在程序中多次出現的數字或字符串
const int MAX=100;//C++語言的const常量
const float PI=3.1415926
·需要對外公開的常量放在頭文件中,不需要對外公開的常量放在定義文件的頭部。為便于管理,可以把不同模塊的常量集中存放在一個公共的頭文件中。
·如果某一常量與其他常量密切相關,應在定義中包含這種關系,而不應給出一些孤立的值。
const float RADIUS=100;
const float DIAMETER=RADIUS*2;
3.3 const在函數中的使用
3.3.1 const修飾函數參數
·被const修飾的輸入參數,在函數中不能修改它的值,防止意外的變動發生,能加強函數的健壯性。
·作為返回值使用,說明函數的返回值是不能被修改的。在取得返回值時應用const int a=func()
·const修飾類成員函數體
const修飾的函數體稱為常函數,說明函數是不能修改類中成員的值的,不過只能用于修飾類的成員函數中。
3.3.2 實例代碼

/**//**//**//**********************************/

/**//**//**//*說明:演示const在函數中的作用
/*const:修飾參數
/*const:修飾返回值
/*const:修飾函數體
/**********************************/
#include<iostream.h>
#include<assert.h>
//const輸入修飾輸入參數,在函數中不能修改它的值,防止意外的變動發生,能加強函數的健壯性
char* StringCopy(char *strDestination,const char *strSource)


{
assert((strDestination!=NULL)&&(strSource!=NULL));
char* address=strDestination;
while((*strDestination++=*strSource++)!='\0')
NULL;
return address;
}
//const修飾返回值
const char *GetString(void)


{
char* szOut="日期輸出結束";
return szOut;
}
//類DTime
class DTime


{
//操作
public:
DTime(int iYear,int iMonth,int iDay)

{
m_nYear=iYear;
m_nMonth=iMonth;
m_nDay=iDay;
}

int GetYear() const
{return m_nYear;}//const修飾函數體

int GetMonth() const
{return m_nMonth;}

int GetDay() const
{return m_nDay;}
public:
int m_nYear;
int m_nMonth;
int m_nDay;
};

int main()


{
char szOutStr[256];
char* szInStr="輸入年月日";
StringCopy(szOutStr,szInStr);
cout<<szOutStr<<endl;

int nYear;
int nMonth;
int nDay;

cin>>nYear;
cin>>nMonth;
cin>>nDay;

DTime dt(nYear,nMonth,nDay);

cout<<dt.GetYear()<<"-"<<dt.GetMonth()<<"-"<<dt.GetDay()<<endl;
const char* str=GetString();
cout<<str<<endl;
return 0;
}
3.4 const指針
const指針有兩種格式,一種是指針常量,表示指針本身是常量,指針值不可修改,指向的內容可以修改;另外一種是指向常量的指針,表示指向的對象是常量,指針值可以修改。
① 指針常量,指針本身是常量,參考代碼如下:
char ch[5]="lisi";
char* const pStr=ch;
pStr="zhangsan";//錯誤
*pStr='W';//正確
② 指向常量的指針,指針值可以修改,指向內容不可改變,參考代碼如下:
char ch[5]="lisi";
char const *pStr=ch;
pStr="wangwu";//正確
*pStr='w'//錯誤
3.5 類const成員變量的初始化
const修飾的成員變量,必須進行初始化,且不能更新。類中聲明const成員變量,只能通過初始化列表的方式生成構造函數對成員變量進行初始化。
(代碼有問題,修改ing)
程序的運行結果為:
100:10:100
0:10:0
在程序中,聲明了如下3個常數據成員。
·const int &r;
·const int a;
·static const int b;
其中,r是常int型引用,a是常int型變量,b是靜態常int型變量。程序中對靜態數據成員b進行初始化。
構造函數的格式如下所示:
Ext(int i):a(i),r(a)
{
}
其中,冒號后面是一個數據成員初始化列表,它包含兩個初始化項,用逗號進行了分隔,因為數據成員a和r都是常類型的,需要采用初始化格式。
3.6 const與宏常量的區別
1.const常量有數據類型,而宏常量沒有數據類型
編譯器可以對前者進行類型安全檢查,而對后者只能進行字符替換,沒有安全檢查,并且在字符替換時可能會產生意料不到的錯誤。
2.編譯器對二者的調試
有些集成化的調試工具可以對const常量進行調試,但是不能對宏常量進行調試。在C++程序中只使用const常量而不適用宏常量,即const常量完全取代宏常量。
4、 sizeof使用技巧
4.1、sizeof運算符的特點
sizeof是一個單目的操作符,用于計算操作數的存儲大小,不過它更像是一個特殊的宏,因為它在編譯階段就已經求值了。比如
#include <iostream.h>
void main()


{
int a=0;
cout<<sizeof(a=3)<<endl;
cout<<a<<endl;
}
輸出結果為4、0而不是4、3,就在于sizeof在編譯階段處理的特性,由于sizeof不能變編譯成機器碼,所以在sizeof作用范圍內,也就是()里面的內容也不能被編譯,而是被替換成類型。=操作符返回左操作數的類型,所以a=3相當于int,而代碼頁被替換為:
int a=0;
cout<<4<<endl;
cout<<a<<endl;
4.2、sizeof的應用技巧
1)用于數據類型
利用sizeof運算符計算該類型占用的字節數,sizeof的使用形式為sizeof(type),數據類型必須用括號括住。
2)用于普通數據類型的變量
sizeof使用形式:sizeof(var_name)或sizeof var_name,變量名可以不用括號括住。如sizeof(var_name)、sizeof var_name等都是正確形式。帶括號的用法更普遍,大多數程序員采用這種形式。
3)用于指針
當操作數是指針時,sizeof依賴于編譯器。例如在Microsoft C/C++6.0中,near類指針字節數為2,far、huge類指針字節數為4.(near類,far、huge類是什么?)
4)用于數組
當操作數具有數組類型時,其結果是數組的總字節數。
#include<iostream.h>
void main()


{
char ss[100]="0123456789";

int nn[100]=
{0};
int nSS=sizeof(ss);
int nSSFirst=sizeof(*ss);
int nNN=sizeof(nn);
cout<<"nSS="<<nSS<<endl;
cout<<"nSSFirst="<<nSSFirst<<endl;
cout<<"nNN="<<nNN<<endl;
}
在VC++6.0的輸出結果
nSS=100
nSSFirst=1
nNN=400
5)用于結構體
在默認情況下,為了方便對結構體內的元素訪問和管理,當結構體內的長度都小于處理器位數的時候,便以結構體中最長的數據元素為對齊單位,也就是說結構體的長度大于最長的數據元素的整數倍。如果結構體內存長度大于處理器的位數,那么就以處理器的位數為對齊單位。但是結構體內類型相同的連續元素將在連續的空間內和數組一樣
詳細解釋可看:http://hi.csdn.net/link.php?url=http://topic.csdn.net%2Fu%2F20100125%2F18%2F71fdb3a4-36a4-4c0f-a7ea-b9dcd13ef6ec.html
#include<iostream.h>
struct A


{
char ch;
int n;
};
void main()


{
int n=sizeof(A);
cout<<"sizeof(A)="<<n<<endl;
cout<<sizeof(char)<<endl;
cout<<sizeof(int)<<endl;
}
6)用于類
sizeof運算符對于類的用法和對結構體的用法是一致的。
#include<iostream.h>

class A


{
char ch;
int a;
int b;
};
class B


{

};
class C


{
static int sVale;
};
void main()


{
int n=sizeof(A);
int m=sizeof(B);
int k=sizeof(C);
cout<<"sizeof(A)="<<n<<endl;
cout<<"sizeof(B)="<<m<<endl;
cout<<"sizeof(C)="<<k<<endl;
}
其中,class A中實際變量占用了9字節,因為類的長度一定是最長的數據元素的整數倍,所以結果為12。對于編譯器我而言,即便類是空的,編譯器也會給出一個空間,所以sizeo(B)=1;因為靜態變量時存放在全局數據區里面的,而sizeof只計算棧中分配的大小,所以sizeof(C)=1。
4.3、sizeof與srtlen()的區別
1、二者的區別
sizeof是操作符,strlen是函數。
sizeof可以用類型做參數,strlen只能用char*做參數,且必須是以“\0”結尾的
2、實例代碼
#include<iostream.h>
#include<string.h>
void main()


{
char* str=new char[100];
cout<<"sizeof(str)="<<sizeof(str)<<endl;
cout<<"strlen(str)="<<strlen(str)<<endl;
char s;
cout<<"sizeof(s)="<<sizeof(s)<<endl;
cout<<"strlen(&s)="<<strlen(&s)<<endl;
}
說明:strlen返回的是實際串長,而sizeof返回的是變量占用的空間
例 如
memset(str, 0, sizeof(str));//用strlen和sizeof()有什么區別
用sizeof的話,只給str所指向的內存塊連續4個字節清0
用strlen的話,只給str所指向的字符串全部清0
sizeof(str)返回這個指針變量所占的內存字節數目
strlen(str)返回str所指向的字符串的長度
如果還想獲得更多關于《Visual C++代碼參考與技巧大全》的內容,可點擊下面網址,http://m.shnenglu.com/kangnixi/archive/2010/01/13/105591.html