2009-06-05 67 views
22

我正在嘗試使用特定類的內聯成員函數。例如,函數聲明和實現內聯,而不是這樣的:內聯函數鏈接器錯誤

int GetTplLSize(); 

在.cpp文件:

在頭文件

int NeedleUSsim::GetTplLSize() 
{ 
    return sampleDim[1]; 
} 

出於某種原因,如果我把「內聯「關鍵字在任何一個執行和聲明中,以及在兩個地方,我都會得到鏈接器錯誤,如下所示:

 
Creating library C:\DOCUME~1\STANLEY\LOCALS~1\TEMP\MEX_HN~1\templib.x and object C:\DOCUME~1\STANLEY\LOCALS~1\TEMP\MEX_HN~1\templib.exp 
mexfunction.obj : error LNK2019: unresolved external symbol "public: int __thiscall NeedleUSsim::GetTplLSize(void)" ([email protected]@@QAEHXZ) referenced in function _mexFunction 
mexfunction.mexw32 : fatal error LNK1120: 1 unresolved externals 

    C:\PROGRA~1\MATLAB\R2008B\BIN\MEX.PL: Error: Link of 'mexfunction.mexw32' failed. 

需要什麼才能擺脫這種錯誤(即我在做這些內聯成員函數方面做了什麼錯誤)?

回答

23

然後,您需要將函數定義放入標題中。暗示編譯器內聯最簡單的方法是包含方法體類聲明中,如:


class NeedleUSsim 
{ 
    // ... 
    int GetTplLSize() const { return sampleDim[1]; } 
    // ... 
}; 

,或者,如果你堅持要單獨的聲明和定義:


class NeedleUSsim 
{ 
    // ... 
    int GetTplLSize() const; 
    // ... 
}; 

inline int NeedleUSsim::GetTplLSize() const 
{ return sampleDim[1]; } 

的定義必須是在使用該方法的每個翻譯單元中都可見。

+0

這是唯一的方法嗎? (爲了可讀性的原因,我想分開聲明和實現) – stanigator 2009-06-05 00:46:56

+1

基本上是的。編譯器在編譯對它的調用時必須知道函數的主體,因此主體必須位於包含的頭文件中。 但是,您仍然可以在類聲明中聲明該函數,並在稍後的頭文件中添加該實現。 – Hans 2009-06-05 01:03:54

+0

我明白了。我想我只需要用這種方式編寫代碼就行了。感謝您的建議。 – stanigator 2009-06-05 02:10:53

2

如果你有一個內聯函數,你應該把定義放在頭文件中。

+0

我試着把inline關鍵字放在頭文件中的定義上,我仍然得到相同的鏈接器錯誤。 – stanigator 2009-06-05 00:12:59

+2

不只是inline關鍵字,整個定義應該放在頭文件中。因此,將它從.cpp文件移動到.h文件中。 – ChrisInEdmonton 2009-06-05 00:17:48

+1

定義,不是聲明。 – 2009-06-05 00:19:19

17

從C++ FAQ精簡版

如果你把內聯函數的定義 到一個.cpp文件,如果 是從其他.cpp文件調用, 你會得到一個「無法解析的外部「 來自鏈接器的錯誤。

How do you tell the compiler to make a member function inline?

+0

不幸的是,因爲我剛剛發現困難的方式,這是不是在MSVC 2013年和2015年的情況。我有一個內聯在一個CPP文件中(在一個庫中),它的代碼是從一些完全不同的CPP源代碼中調用的,它們有一個內聯的同名(但代碼略有不同,所以結果確實打破了測試)。我認爲這是該開發環境中的一個錯誤。很難找到... – chksr 2017-11-15 14:05:20

3

正如其他人已經指出的那樣,你需要將內聯函數的定義移到頭文件中,就像這樣:

class NeedleUSsim 
{ 
    // ... 
    inline int GetTplLSize() { return sampleDim[1]; } 
    // ... 
}; 

這樣做的原因是,編譯器在看到對內聯函數的調用時需要知道內聯的代碼。如果將函數的定義保留在NeedleUSsim類的.cpp文件中,則編譯器爲其生成的代碼將陷入NeedleUSsim目標文件中。由於編譯器只能讀取源代碼—,因此它永遠不會窺探到另一個類的目標文件—,因此在編譯另一個.cpp文件時,無法知道用什麼代碼替換調用。