2017-10-08 51 views
0

這些是我一直收到錯誤:即時對象初始化失敗,錯誤LNK2005

LNK2005 "class Sally TestObject" ([email protected]@[email protected]@A) already defined in Source.obj Project2 c:\Users\W8User\documents\visual studio 2015\Projects\Project2\Project2\Source1.obj 

LNK1169 one or more multiply defined symbols found Project2 c:\users\w8user\documents\visual studio 2015\Projects\Project2\Debug\Project2.exe 

我真的不明白的地方都來自這些錯誤。我試過在其他SO線程或微軟網站上搜索,但沒有任何幫助。

這些都是我的文件:

Source.cpp

#include <iostream> 
#include "Header.h" 

int main() { 

    std::cout << TestObject.ReturnTruth(); 

    return 0; 
} 

Header.h

#pragma once 

class Sally 
{ 
public: 

    bool ReturnTruth(); 

} TestObject; 

Source1.cpp

#include "Header.h" 

bool Sally::ReturnTruth() 
{ 
    return 1; 
} 

我所知道的是將對象初始化移動到Source.cpp文件中並不會立即在頭文件中執行它,但是由於即時初始化是可能的,爲什麼我不使用它?

+0

你說的「即時初始化」的意思是,爲什麼你覺得這個應該工作? – aschepler

+0

在頭文件中有一個對象**定義**('TestObject')。不要這樣做。 –

回答

1

假設您有兩個不同的.cpp文件,每個文件都包含您的Header.h標題。然後,那些cpp文件中的每一個獲取此代碼併入它:

class Sally 
{ 
public: 

    bool ReturnTruth(); 

} TestObject; 

其結果是,每個文件包含名爲Sally類型的TestObject一個對象的定義。這打破了單一定義規則,因爲只有所有翻譯單元中的每個對象最多隻有一個定義,並且它在鏈接器錯誤中顯現出來。

如果你想申報Sally類型的一個全局對象,更改標題宣佈Sally類型的extern對象,像這樣:

class Sally 
{ 
public: 

    bool ReturnTruth(); 

}; 
extern Sally TestObject; 

這是一個聲明,不是定義,可以重複聲明對象。

然後,選擇.cpp文件 - 可能是一個在那裏你實現Sally成員函數 - 並添加此行:

Sally TestObject; 

,在一個地方把對象的定義和因此修復了單個定義規則問題和鏈接器問題。

+0

使用extern類對象並在源文件中聲明並在源文件中聲明它沒有任何類型的頭文件內聲明有什麼區別? – Suiko

+0

是的 - 如果您只是在源文件中聲明它,那麼它對該源文件之外的任何內容都不可見。如果這就是你想要做的,我會更進一步,將'TestObject'的聲明封裝在一個匿名的命名空間中,以確保沒有其他人可以訪問它。 – templatetypedef

+0

@templatetypedef:可能「不可見」是誤導性的,因爲源文件中非靜態(或匿名命名空間)中的每個「全局」變量都是可訪問的,因此是「可見的」。 –

0

你的每一個地方#include "Header.h"你將有一個TestObject的實例,除非你的編譯器可以將所有這些摺疊成一個單例,否則你將有幾個獨立的,不相關的實例。

該錯誤建議您已經犯了一個錯誤。解決這個問題的一種方法是在頭文件中定義:

extern Sally TestObject; 

這就明確表示這將在別處實例化。然後在Source1.cpp做出明確實例:

Sally TestObject; 

然後你的主文件就會知道去哪裏找這個東西。

目前還不清楚你是否首先想要一個單身人士。爲什麼不能在main裏面實例化一個並使用它?

請注意,花時間爲您的源文件提供有意義的名稱。

+0

使用extern類對象並在源文件中聲明它並僅在源文件中聲明它沒有任何類型的頭文件內聲明有什麼區別?哦,我知道這些文件應該有有意義的名字,這些只是IDE中出現的第一個名字。通常我不會使用它們,這次我做了它來顯示無論如何會發生的錯誤。 – Suiko

+0

如果您在源文件中聲明該文件將該實例限制爲文件的範圍,那麼除非您已經定義了某種類型的接口,否則無法訪問它,例如在頭文件。至於名字,像'(untitled).cpp'這樣的東西可以而且會給人一種憤怒的皮疹,所以請保持你的問題乾淨整潔,像這樣的廢話。它有助於避免分心。 – tadman

0

通過在類定義Sally之後直接附加標識符TestObject,您可以在頭文件中定義一個變量。因此,如果不同的翻譯單元包含此頭文件,則會定義兩次具有相同名稱的變量,從而導致鏈接器錯誤。您可以通過只聲明變量,即使用extern -keyword在headerfile,而定義變量,然後在只有一個.cpp -file解決此問題:

所以寫:

Header.h

class Sally 
{ 
public: 

    bool ReturnTruth(); 

}; 

extern Sally TestObject; 

Source1.cpp

#include "header.h" 

Sally TestObject; 
... 

在所有其他CPP-文件:

#include "header.h" 
... 
+0

使用extern類對象並在源文件中聲明並在源文件中聲明它沒有任何類型的頭文件內聲明有什麼區別? – Suiko

+0

@Suiko:沒有,除了必須「猜測」某翻譯單元中存在這樣的變量。但實際上,每個在翻譯單元中定義並且沒有標記爲「靜態」或在匿名名稱空間中定義的變量對其他翻譯單元都是可見的;請注意,'extern Sally Testobject'只是給了編譯器關於另一個翻譯單元中會有這樣一個對象的信息(那麼只有鏈接器纔會抱怨)。 –

相關問題