警告C4661:没有为显式模板实例化请求提供合适的定义

时间:2017-05-24 13:53:33

标签: c++ c++11 templates visual-c++ visual-studio-2017

我编写了一个类模板并在不同的DLL中使用它,所以希望隐藏实现的某些部分。

要做到这一点,我使用“模板实例化”,但导出它,像这样,这里是头文件:

#include <iostream>
#include <exception>

using namespace std;

template<typename T>
class __declspec(dllexport) Templated
{
    public:
        Templated();
};

template __declspec(dllexport) Templated<int>;

int main()
{
   cout << "Hello World" << endl; 
}

定义在一个单独的文件(.cpp)

template<typename T>
Templated<T>::Templated() {}

template Templated<int>;

我的问题是我收到了警告,即使实例化被标记为已导出!

您可以在此处测试此代码:http://webcompiler.cloudapp.net/,它会生成C4661警告!

这是正常的吗?

1 个答案:

答案 0 :(得分:6)

您声明了模板的显式实例化。精细。但是你没有提供构造函数的定义:你只能声明它。并且没有任何定义,模板也没有定义。

您必须在模板本身中提供定义:

...
public:
    Templated() {};  // empty but defined ctor
...

或专业化:

Templated<int>::Templated() {
}

从您的评论和编辑到问题,该定义位于另一个cpp文件中。问题是对于编译器,每个cpp文件都是不同的翻译单元。换句话说,当编译第一个文件时,编译器不知道另一个文件。这就是为什么你得到警告而不是错误的原因:警告意味着嘿嘿程序员,你声明我想要一个Templated的专门实例化,但我找不到它的构造函数。希望您已在另一个翻译单元中定义它,因为如果您还没有在链接时收到错误。正如您在其他文件中实际定义的那样,您可以放心地忽略该警告。

警告只表示 uncommon 正在发生。通常,预期明确专业化的声明与其所有必需定义在同一翻译单元中。恕我直言,你应该坚持使用这种用法来避免警告,更重要的是,要有一个更易于维护的应用程序。