2017-10-08 97 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'只是给了编译器关于另一个翻译单元中会有这样一个对象的信息(那么只有链接器才会抱怨)。 –