今天複習C++ Primer的時候,看到了關於C++類的內聯成員函數的放置,應該放在標頭檔中。那麼這到底是為什麼
呢?僅僅是一種代碼規範問題還是必須這樣做呢?
下面我就來講講我自己的理解吧。要徹底理解這個問題,首先就要瞭解下函數的聲明和定義了。我們知道,函數可以
在多處聲明,但只能在一個地方定義,不然就會出現重定義。大部分函數預設是外部連結,而inline函數預設為內部鏈
接。也就是說inline函數只能在本檔案中使用,對其他檔案是不可見的。一般我們使用某個類的時候,都是在檔案中加
上該類的標頭檔,以便我們可以使用該類的介面。而我們類的成員函數的實現都是放在相應的.cpp檔案中的,而在.h
檔案中聲明。這樣我們便可以通過.h檔案中的成員函數的聲明找到其定義,繼而使用成員函數了。但如果將inline函數
放在.cpp檔案中,那麼其只對.cpp檔案有效,這樣我們就無法訪問它了。所以我們將其放在類的聲明的標頭檔中,這
樣通過包含該標頭檔來使用它。
下面寫個實際的例子來說明一下,我先把內嵌函式放到類聲明的標頭檔中:
/*test.h*/#ifndef TEST_H#define TEST_H#include <iostream>using std::cout;using std::endl;class test{public:test():x(10){}inline void print();void display (int y);private:int x;};void test::print(){cout << x << endl;}#endif
/*test.cpp*/#include <iostream>#include "test.h"using std::cout;using std::endl;void test::display(int y){cout << x * y << endl;}
/*main.cpp*/#include <iostream>#include "test.h"using namespace std;int main(){test T;T.display(10);T.print();system("pause");return 0;}
運行結果正常,下面來看看將內嵌函式放到.cpp中去:
/*test.h*/#ifndef TEST_H#define TEST_H#include <iostream>using std::cout;using std::endl;class test{public:test():x(10){}inline void print();void display (int y);private:int x;};#endif
/*test.cpp*/#include <iostream>#include "test.h"using std::cout;using std::endl;void test::print(){cout << x << endl;}void test::display(int y){cout << x * y << endl;}
測試函數和上面的main.cpp是一樣的。這是出現了錯誤:
error LNK2019: 無法解析的外部符號 "public: void __thiscall test::print(void)" (?print@test@@QAEXXZ),該符號在函
數 _main 中被引用。如果我將測試函數改為:
int main(){test T;T.display(10);//T.print();system("pause");return 0;}
那麼運行結果正常。從此可以得出結論:內嵌函式放在標頭檔或者.cpp中都是沒有錯的,但如果我們需要在程式中訪
問它,那麼就必須將其放在標頭檔中。