2017-01-05 95 views
0

*******编辑*******C++编译问题 - 用cl.exe编译正常,但不会从Visual Studio 2015编译

一位读者建议我的问题是重复的的问题发现here。在包头结束

  • 1)的#include实现文件(这是我做我的解决方案)或
  • 2)显式实例所有的:对这个问题的回应领先给出了两个解决方案模板实例我需要在实现文件的末尾

由于我已经尝试过这种解决方案,这不是重复的问题。

这个问题,正如下面的Ben Voigt所说(谢谢),与Visual Studio有关。将“C/C++编译器”的“项目类型”更改为“C/C++头文件”以解决MyClass.cpp文件问题。

****编辑完****

我是一个初学者C++和我遇到一个问题,试图在Visual Studio 2015年编译下面的程序中的程序中使用精编铛编译器在我的Mac上。该程序也使用VS2015的开发人员命令提示符使用cl.exe进行了良好编译。我想这意味着有些东西在我的Visual Studio项目中配置错误,但我还没有找到解决方案。

下面的代码:

/** @file MyInterface.h */ 

#ifndef MY_INTERFACE_ 
#define MY_INTERFACE_ 

template<class ItemType> 
class MyInterface 
{ 
public: 
    virtual void sayHello() const = 0; 
}; 

#endif 

/** @file MyClass.h */ 

#ifndef MY_CLASS_ 
#define MY_CLASS_ 

#include "MyInterface.h" 

template<class ItemType> 
class MyClass : public MyInterface<ItemType> 
{ 
private: 
    ItemType myItem; 

public: 
    MyClass(); 
    void setItem(const ItemType& newItem); 
    void sayHello() const; 
}; 

#include "MyClass.cpp" 
#endif 

/** Implementation file for MyClass. 
    @file MyClass.cpp */ 

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

template<class ItemType> 
MyClass<ItemType>::MyClass() 
{ 
} 

template<class ItemType> 
void MyClass<ItemType>::setItem(const ItemType& newItem) 
{ 
    myItem = newItem; 
} 

template<class ItemType> 
void MyClass<ItemType>::sayHello() const 
{ 
    std::cout << "Hello! My Item is: " << myItem << std::endl; 
} 

/** @file test.cpp */ 

#include "MyClass.h" 
#include <string> 

int main() 
{ 
    MyClass<std::string> classOne; 
    classOne.setItem("foo"); 
    classOne.sayHello(); 

    MyClass<int> classTwo; 
    classTwo.setItem(7); 
    classTwo.sayHello(); 
} 

当我在一个目录合并这些文件并运行命令:

cl test.cpp 

从VS2015开发人员命令提示符,它编译正确。我得到一个test.exe可执行文件返回:

test.exe 
Hello! My item is: foo 
Hello! My item is: 7 

到目前为止,这么好。

当我尝试在Visual Studio 2015中完成此项目时,问题就开始了。我为Visual C++启动了一个“空项目”并添加了这些完全相同的文件。然而,当我建立这个项目我得到的错误信息:

Error C2995 'MyClass<ItemType>::MyClass(void)': function template has already been defined 
Error C2995 'void MyClass<ItemType>::setItem(const ItemType &)': function template has already been defined 
Error C2995 'void MyClass<ItemType>::sayHello(void) const': function template has already been defined 

错误信息让我相信,我有一个循环依赖。罪魁祸首似乎是MyClass.h文件中的#include "MyClass.cpp",但这对模板编译是必需的。如果没有这个包含,编译器就无法看到模板的实例化,也不知道对应于泛型ItemType(或者我的教科书说)的实际数据类型。

在努力满足Visual Studio的生成过程中,我从MyClass.h文件中删除了#include "MyClass.cpp,但后来我得到这些错误:

Error LNK2019 unresolved external symbol "public: __thiscall MyClass<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >::MyClass<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >(void)" ([email protected][email protected][email protected]@[email protected]@[email protected]@[email protected]@[email protected]@@@[email protected]) referenced in function _main 
Error LNK2019 unresolved external symbol "public: __thiscall MyClass<int>::MyClass<int>(void)" ([email protected]@@[email protected]) referenced in function _main 
Error LNK2019 unresolved external symbol "public: void __thiscall MyClass<int>::setItem(int const &)" ([email protected][email protected]@@[email protected]) referenced in function _main 

有六个这样的错误(仅示出三个),都是未解析的外部符号。

在这一点上,我不知道还有什么要尝试。如果我将实现文件包含在头文件中,编译器会大声说我有循环依赖关系,如果我不在头文件中包含实现文件,那么我有无法解析的外部符号。

在这个问题上的任何帮助,将不胜感激:)

+3

模板定义需要在.h文件中,并且您不应该#include一个.cpp文件。 –

+0

http://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented -in-the-header-file – drescherjm

+2

@latedeveloper:这是一个惯例,而不是一个需要。 –

回答

2

因为你#include MyClass.cpp,它不是一个编译单元本身,它是一个头文件。确保Visual Studio被告知不要单独构建它,默认情况下,它假定.h文件是标题,.cpp是每个单独编译的单元。

访问项目属性并将“项目类型”从“C/C++编译器”更改为“C/C++头文件”。

enter image description here

这有效地通过添加的所有文件

cl test.cpp MyClass.cpp 

默认生成的(有效)命令,这将导致恰好改变了build命令工作版本

cl test.cpp 

如果您在命令行键入相同的错误。

还有其他一些方法可以将其从构建命令中删除,例如在解决方案资源管理器的右键菜单中找到“从项目中排除文件”,但这样做不便于编辑/导航到。正确标记为头文件将为您在调试过程中提供Intellisense自动完成,转到定义和源视图的最佳体验。