2010-03-04 35 views
4

我得到的編譯錯誤:C++的內聯函數範圍

Error 7 error C2084: function 'Boolean IsPointInRect(...)' already has a body

在我的內聯函數,該函數聲明如下,以CPP文件:

inline Boolean IsPointInRect(...) 
{ 
... 
} 

我有完全一樣的功能在另一個cpp文件中。這可能會導致問題?我該如何解決它?

+1

@matt:編譯器錯誤的事實使得這個聲音更像是違反了ODR,而不是下面的靜態/名稱空間解決方案將解決的鏈接問題。你在哪裏聲明和IsPointInRect的定義?請在問題中顯示他們。 – quamrana 2010-03-04 10:33:20

+1

@matt:不,問題不是由其他cpp文件中的定義引起的。你在這個翻譯單元中有多個定義。找到他們並修復它。我們無法從這裏看到您的代碼。 – AnT 2010-03-04 22:27:44

回答

14

由於litb和AndreyT指出,這個答案沒有解決實際問題 - 請參閱litbs答案的細節。


雖然static,如Ofir said,給你內部聯動,「C++方法」是使用未命名空間:

namespace 
{ 
    inline Boolean IsPointInRect(/*...*/) { /*...*/ } 
} 

§7.3.1.1/ 1

An unnamed-namespace-definition behaves as if it were replaced by

namespace unique { /* empty body */ } 
using namespace unique; 
namespace unique { namespace-body } 

where all occurrences of unique in a translation unit are replaced by the same identifier and this identifier differs from all other identifiers in the entire program.

§7.3.1.1/ 2補充說:

The use of the static keyword is deprecated when declaring objects in a namespace scope (see annex D); the unnamed-namespace provides a superior alternative.

+0

錯誤 - 這裏有沒有名字的命名空間有什麼用?它們在這裏同樣會失敗:'namespace {inline void a(){}} namespace {inline void a(){}}'(提供主體兩次!),並且它們不會提供任何內聯的「避免」鏈接器錯誤函數(內聯函數可以在程序中定義多次 - 只要在不同的翻譯單元中)。 – 2010-03-04 22:02:10

+0

事實上,現在在VC中測試它 - 感謝修正。對於這個問題的猜測以及對其他答案的反應,這非常重要。我會保留現在的答案以供參考 – 2010-03-04 22:39:25

+0

嗯,爲什麼現在我的答案被接受了?現在有什麼問題? – 2010-03-06 20:31:54

0

擺脫其中之一?你期望什麼?

也許你應該解釋爲什麼需要兩個版本...

+0

因爲我沒想到內聯函數可以在代碼中隨處訪問。 – clamp 2010-03-04 09:45:08

+0

啊,在這種情況下,你需要「靜態」修飾符,而不是內聯。 – 2010-03-04 17:48:25

+0

或「extern」,如果您只是想聲明函數而不重新定義。 – 2010-03-04 17:48:51

6

他們將在適當的命名空間,使簡單的解決方案。即使匿名也會工作。

+0

是的,這是舊的「靜態」解決方案的C++替代品。爲什麼這是downvoted? – 2010-03-04 09:58:57

0

您可以添加「靜態」或「外部」中的「內聯」前,我認爲(我可以使用GCC時知道),例如:

static inline Boolean IsPointInRect(...) { ... } 
2

如果您將它們都變成一個頭應該解決它的文件。或申報其中一個或兩個static。或者,如果您使用的是MSVC,請將它們聲明爲__declspec(selectany)

1

將您的內聯函數保存在頭文件中,並使用include guard來確保文件不包含兩次。

3

正如其他人所說,如果你真的想限制的功能cpp文件的範圍,那麼你應該把它放在一個命名空間,例如

namespace // anonymous 
{ 
    inline bool IsPointInRect(...) 
    { 
     ... 
    } 
} 

然而,它似乎是一個維護問題,以具有相同體相同的功能(即他們都做同樣的事情)在兩個不同的地方 - 複製/粘貼風格。如果兩種不同的功能具有相同的名稱,但具有不同的主體,那麼這也是等待發生的問題。

顯然你有性能問題(因此內聯),但它最好只有在一個地方寫的功能!至少把它放在一個包含你需要的地方的頭文件(匿名命名空間)中。實際上,您應該「乾淨利落」地完成這項工作,然後只在您的配置文件告訴您時才恢復到性能特定的方法。

乾杯,

Michael 
0

有2種方式聲明內聯函數:

  1. 裏面的類:任何函數定義在類內部是一個內聯函數。

  2. 課外:如果你在課堂外定義它,那麼你需要使用關鍵字'inline'和函數簽名。

如果你有在不同的類中定義的另一個同名的函數,那麼它將不會,只要您使用範圍解析運算符(拋出任何異常::)和點()與正常對象名稱。

1

我有完全一樣的功能

你的意思是使用相同的名稱和類型的功能,或者你的意思是使用相同的名稱,類型和身體的功能?後者沒有任何問題,實際上這就是inline所做的 - 它允許您在不同的翻譯單元中以相同的方式定義相同的功能。對於前者,您必須確保該函數具有文件範圍。 inline不提供函數文件範圍,static和未命名的名稱空間都有。一個未命名的命名空間是在C++中使用它的首選方式,至少根據標準:static已棄用。

0

1.使用extern和static關鍵字

2.declare它一個名稱空間

10

裏面你有在這個線程一些錯誤的答案。在你的代碼的問題是,你在你的代碼兩次定義你的內聯函數:

inline Boolean IsPointInRect(...) { ... } 
inline Boolean IsPointInRect(...) { ... } 

inline意願,別人說正確的,既保護您不必通過定義兩倍的功能上升錯誤。您不需要static,也不需要未命名的名稱空間。另請注意,您不應定義其他翻譯單元(處理並擴展所有#include和#if等文件).cpp文件中應使用的內聯函數。他們的定義必須被所有使用它們的翻譯單元所知 - 所以在這種情況下,他們的定義只能在的頭文件中 - 而不是在.cpp和頭文件中 - 這會導致你得到的錯誤。

您還需要頭部防護,以避免在每個標題

// file foo.h 
#ifndef POINTS_H_INCLUDED 
#define POINTS_H_INCLUDED 

inline Boolean IsPointInRect(...) { ... } 

#endif 


// file bar.cpp 
#include "foo.h" 
// does not include the content a second time anymore - the guards aboid it: 
#include "foo.h" 

和上面的問題,您應該確保包括一個.cpp文件到另一個.cpp文件(.cpp文件是不應該被包括在內)。您應該將頭文件包含到.cpp文件中。