2017-01-05 92 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自動完成,轉到定義和源視圖的最佳體驗。