?? 02.2.10 c++類的設(shè)計(jì)習(xí)慣及頭文件重復(fù)包含問題的解決.txt
字號(hào):
2.2.10 C++類的設(shè)計(jì)習(xí)慣及頭文件重復(fù)包含問題的解決
在設(shè)計(jì)一個(gè)類的時(shí)候,通常是將類的定義及類成員函數(shù)的聲明放到頭文件(即.h文件)中,將類中成員函數(shù)的實(shí)現(xiàn)放到源文件(即.cpp)中。對(duì)于animal類需要animal.h和animal.cpp兩個(gè)文件,同樣,對(duì)于fish類需要fish.h和fish.cpp。對(duì)于main()函數(shù),我們把它單獨(dú)放到EX10.cpp文件中。
往一個(gè)現(xiàn)有工程添加頭文件(.h文件)或源文件(.cpp文件)有兩種方式:一種是在打開的工程中,單擊【File】→【New】,在左邊的Files標(biāo)簽頁下,選擇C++ Header File或C++ Source File,然后在右邊的File文本框中,輸入頭文件或源文件的文件名,如animal.h或animal.cpp,單擊【OK】按鈕。如圖2.16所示。
圖2.16 新建頭文件或源文件
另一種方式是在EX10的工程目錄下,單擊鼠標(biāo)右鍵,選擇【新建】→【文本文檔】,然后將“新建文本文檔.txt”改名為“animal.h”(因.h和.cpp文件都是文本格式的文件),依同樣的方法,建立animal.cpp、fish.h、fish.cpp三個(gè)文件,然后在打開的工程中,選擇【Project】→【Add To Project】→【Files】,選擇animal.h、animal.cpp、fish.h、fish.cpp這四個(gè)文件,單擊【OK】按鈕,如圖2.17所示。
圖2.17 添加頭文件和源文件到工程中
代碼如例2-24所示。
例2-24
animal.h
//在頭文件中包含類的定義及類成員函數(shù)的聲明
class animal
{
public:
animal();
~animal();
void eat();
void sleep();
virtual void breathe();
};
animal.cpp
//在源文件中包含類中成員函數(shù)的實(shí)現(xiàn)
#include "animal.h" //因?yàn)樵诰幾ganimal.cpp時(shí),編譯器不知道animal到底
是什么,所以要包含animal.h,這樣,編譯器就知道animal
是一種類的類型
#include <iostream.h> //在包含頭文件時(shí),<>和""有什么區(qū)別?<>和""表示編譯器
在搜索頭文件時(shí)的順序不同,<>表示從系統(tǒng)目錄下開始搜索,
然后再搜索PATH環(huán)境變量所列出的目錄,不搜索當(dāng)前目錄;
""是表示先從當(dāng)前目錄搜索,然后是系統(tǒng)目錄和PATH環(huán)境
變量所列出的目錄。所以如果我們知道頭文件在系統(tǒng)目錄下
就可以直接用<>,這樣可以加快搜索速度
animal::animal() //::叫做作用域標(biāo)識(shí)符,用于指明一個(gè)函數(shù)屬于哪個(gè)類或一
個(gè)數(shù)據(jù)成員屬于哪個(gè)類。::前面如果不跟類名,表示是全局
{ 函數(shù)(即非成員函數(shù))或全局?jǐn)?shù)據(jù)
}
animal::~animal()
{
}
void animal::eat() //注意:雖然我們?cè)诤瘮?shù)體中什么也沒寫,但仍然是實(shí)現(xiàn)了
這個(gè)函數(shù)
{
}
void animal::sleep()
{
}
void animal::breathe() //注意,在頭文件(.h文件)中加了virtual后,在源文
件(.cpp文件)中就不必再加virtual了
{
cout<<"animal breathe"<<endl;
}
fish.h
#include "animal.h" //因fish類從animal類繼承而來,要讓編譯器知道
animal是一種類的類型,就要包含animal.h頭文件
class fish:public animal
{
public:
void breathe();
};
fish.cpp
#include "fish.h"
#include <iostream.h>
void fish::breathe()
{
cout<<"fish bubble"<<endl;
}
EX10.cpp
#include "animal.h"
#include "fish.h"
void fn(animal *pAn)
{
pAn->breathe();
}
void main()
{
animal *pAn;
fish fh;
pAn=&fh;
fn(pAn);
}
現(xiàn)在我們就可以按下鍵盤上的F7功能鍵編譯整個(gè)工程了,編譯結(jié)果如下:
為什么會(huì)出現(xiàn)類重復(fù)定義的錯(cuò)誤呢?請(qǐng)讀者仔細(xì)查看EX10.cpp文件,在這個(gè)文件中包含了animal.h和fish.h這兩個(gè)頭文件。當(dāng)編譯器編譯EX10.cpp文件時(shí),因?yàn)樵谖募邪薬nimal.h頭文件,編譯器展開這個(gè)頭文件,知道animal這個(gè)類定義了,接著展開fish.h頭文件,而在fish.h頭文件中也包含了animal.h,再次展開animal.h,于是animal這個(gè)類就重復(fù)定義了。
讀者可以測(cè)試一下,如果我們多次包含iostream.h這個(gè)頭文件,也不會(huì)出現(xiàn)上面的錯(cuò)誤。要解決頭文件重復(fù)包含的問題,可以使用條件預(yù)處理指令。修改后的頭文件如下:
animal.h
#ifndef ANIMAL_H_H //我們一般用#define定義一個(gè)宏,是為了在程序中使用,使程
序更加簡(jiǎn)潔,維護(hù)更加方便,然而在此處,我們只是為了判斷
#define ANIMAL_H_H ANIMAL_H_H是否定義,以此來避免類重復(fù)定義,因此我們沒有為
其定義某個(gè)具體的值。在選擇宏名時(shí),要選用一些不常用的名字,
class animal 因?yàn)槲覀兊某绦蚪?jīng)常會(huì)跟別人寫的程序集成,如果選用一個(gè)很常用
的名字(例如:X),有可能會(huì)造成一些不必要的錯(cuò)誤
{
public:
animal();
~animal();
void eat();
void sleep();
virtual void breathe();
};
#endif
fish.h
#include "animal.h"
#ifndef FISH_H_H
#define FISH_H_H
class fish:public animal
{
public:
void breathe();
};
#endif
我們?cè)倏碋X10.cpp的編譯過程。當(dāng)編譯器展開animal.h頭文件時(shí),條件預(yù)處理指令判斷ANIMAL_H_H沒有定義,于是就定義它,然后繼續(xù)執(zhí)行,定義了animal這個(gè)類;接著展開fish.h頭文件,而在fish.h頭文件中也包含了animal.h,再次展開animal.h,這個(gè)時(shí)候條件預(yù)處理指令發(fā)現(xiàn)ANIMAL_H_H已經(jīng)定義,于是跳轉(zhuǎn)到#endif,執(zhí)行結(jié)束。
通過分析,我們發(fā)現(xiàn)在這次的編譯過程中,animal這個(gè)類只定義了一次。
提示:Windows 2000初始安裝完畢后,對(duì)于已知文件類型的擴(kuò)展名是隱藏的,例如:“test.txt”這個(gè)文件,在資源瀏覽器中看到的是“test”,在這種情況下,修改其文件名為“test.cpp”時(shí),實(shí)際的文件名是“test.cpp.txt”,仍然是文本文件。因此在Win2000下做開發(fā)時(shí),要取消“隱藏已知文件類型的擴(kuò)展名”這一選項(xiàng)。
操作步驟:在資源瀏覽器(或我的電腦)中,選擇菜單中的“工具->文件夾選項(xiàng)(O)…”,選擇“查看”標(biāo)簽頁,將滾動(dòng)欄拖到底端,將“隱藏已知文件類型的擴(kuò)展名”復(fù)選框中的對(duì)號(hào)(√)取消掉,單擊“確定”按鈕。
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -