在設計一個類的時候,通常是將類的定義及類成員函數的聲明放到頭文件(即.h文件)中,將類中成員函數的實現放到源文件(即.cpp)中。對於animal類需要animal.h和animal.cpp兩個文件,同樣,對於fish類需要fish.h和fish.cpp。對於main()函數,我們把它單獨放到EX10.cpp文件中。
往一個現有工程添加頭文件(.h文件)或源文件(.cpp文件)有兩種方式:一種是在打開的工程中,單擊【File】→【New】,在左邊的Files標簽頁下,選擇C++ Header File或C++ Source File,然後在右邊的File文本框中,輸入頭文件或源文件的文件名,如animal.h或animal.cpp,單擊【OK】按鈕。如圖2.16所示。
圖2.16 新建頭文件或源文件
另一種方式是在EX10的工程目錄下,單擊鼠標右鍵,選擇【新建】→【文本文檔】,然後將“新建文本文檔.txt”改名為“animal.h”(因.h和.cpp文件都是文本格式的文件),依同樣的方法,建立animal.cpp、fish.h、fish.cpp三個文件,然後在打開的工程中,選擇【Project】→【Add To Project】→【Files】,選擇animal.h、animal.cpp、fish.h、fish.cpp這四個文件,單擊【OK】按鈕,如圖2.17所示。
圖2.17 添加頭文件和源文件到工程中
代碼如例2-24所示。
例2-24
animal.h
//在頭文件中包含類的定義及類成員函數的聲明
class animal
{
public:
animal();
~animal();
void eat();
void sleep();
virtual void breathe();
};
animal.cpp
//在源文件中包含類中成員函數的實現
#include "animal.h" //因為在編譯animal.cpp時,編譯器不知道animal到底是什麼,所以要包含animal.h,這樣,編譯器就知道animal是一種類的類型
#include <iostream.h> //在包含頭文件時,<>和""有什麼區別?<>和""表示編譯器在搜索頭文件時的順序不同,<>表示從系統目錄下開始搜索,然後再搜索PATH環境變量所列出的目錄,不搜索當前目錄;
""是表示先從當前目錄搜索,然後是系統目錄和PATH環境變量所列出的目錄。所以如果我們知道頭文件在系統目錄下就可以直接用<>,這樣可以加快搜索速度
animal::animal() //::叫做作用域標識符,用於指明一個函數屬於哪個類或一個數據成員屬於哪個類。
::前面如果不跟類名,表示是全局
{ 函數(即非成員函數)或全局數據
}
animal::~animal()
{
}
void animal::eat() //注意:雖然我們在函數體中什麼也沒寫,但仍然是實現了這個函數
{
}
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);
}
現在我們就可以按下鍵盤上的F7功能鍵編譯整個工程了,編譯結果如下:
為什麼會出現類重復定義的錯誤呢?請讀者仔細查看EX10.cpp文件,在這個文件中包含了animal.h和fish.h這兩個頭文件。當編譯器編譯EX10.cpp文件時,因為在文件中包含了animal.h頭文件,編譯器展開這個頭文件,知道animal這個類定義了,接著展開fish.h頭文件,而在fish.h頭文件中也包含了animal.h,再次展開animal.h,於是animal這個類就重復定義了。
讀者可以測試一下,如果我們多次包含iostream.h這個頭文件,也不會出現上面的錯誤。要解決頭文件重復包含的問題,可以使用條件預處理指令。修改後的頭文件如下:
animal.h
#ifndef ANIMAL_H_H //我們一般用#define定義一個宏,是為了在程序中使用,使程序更加簡潔,維護更加方便,然而在此處,我們只是為了判斷
#define ANIMAL_H_H ANIMAL_H_H是否定義,以此來避免類重復定義,因此我們沒有為其定義某個具體的值。在選擇宏名時,要選用一些不常用的名字,
class animal 因為我們的程序經常會跟別人寫的程序集成,如果選用一個很常用的名字(例如:X),有可能會造成一些不必要的錯誤
{
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
我們再看EX10.cpp的編譯過程。當編譯器展開animal.h頭文件時,條件預處理指令判斷ANIMAL_H_H沒有定義,於是就定義它,然後繼續執行,定義了animal這個類;接著展開fish.h頭文件,而在fish.h頭文件中也包含了animal.h,再次展開animal.h,這個時候條件預處理指令發現ANIMAL_H_H已經定義,於是跳轉到#endif,執行結束。
通過分析,我們發現在這次的編譯過程中,animal這個類只定義了一次。
提示:Windows 2000初始安裝完畢後,對於已知文件類型的擴展名是隱藏的,例如:“test.txt”這個文件,在資源浏覽器中看到的是“test”,在這種情況下,修改其文件名為“test.cpp”時,實際的文件名是“test.cpp.txt”,仍然是文本文件。因此在Win2000下做開發時,要取消“隱藏已知文件類型的擴展名”這一選項。
操作步驟:在資源浏覽器(或我的電腦)中,選擇菜單中的“工具->文件夾選項(O)…”,選擇“查看”標簽頁,將滾動欄拖到底端,將“隱藏已知文件類型的擴展名”復選框中的對號(√)取消掉,單擊“確定”按鈕。