我是使用c ++模板编程的新手。我有3个代码文件
的main.cpp
#include "template_test.h"
#include <iostream>
using namespace std;
int main()
{
mytest<int> mt;
mt.method(1);
system("pause");
return 0;
}
template_test.h
#include <iostream>
using namespace std;
template<class T>
class mytest
{
public:
void method(T input){}
};
template<>
void mytest<int>::method(int input)
{
cout << "ok" << endl;
}
template_test.cpp
#include "template_test.h"
//empty
该代码在VS2013中生效。但是,当我将代码更改为2个时,我的代码就出现了问题。
1.第一个是链接器错误代码。
的main.cpp
#include "template_test.h"
#include <iostream>
using namespace std;
int main()
{
mytest<int> mt;
mt.method(1);
system("pause");
return 0;
}
template_test.h
#include <iostream>
using namespace std;
template<class T>
class mytest
{
public:
void method(T input);
};
template<class T>
void mytest<T>::method(T input)
{
cout << " " << endl;
}//explicit specialization here
template<>
void mytest<int>::method(int input)
{
cout << "ok" << endl;
}
template_test.cpp
#include "template_test.h"
//empty
2.第二个输出什么都没有,而不是正确答案'ok'。
的main.cpp
#include "template_test.h"
#include <iostream>
using namespace std;
int main()
{
mytest<int> mt;
mt.method(1);
system("pause");
return 0;
}
template_test.h
#include <iostream>
using namespace std;
template<class T>
class mytest
{
public:
void method(T input){}
};
template_test.cpp
#include "template_test.h"
template<>
void mytest<int>::method(int input)
{
cout << "ok" << endl;
}//move from .h to .cpp file here
c ++模板的奇怪行为让我感到困惑。那么,问题是什么?
答案 0 :(得分:3)
第一个问题是由您的显式专业化
引起的template<>
void mytest<int>::method(int input)
{
cout << "ok" << endl;
}
在类定义和之外的头文件和中定义,没有关键字inline
。
显式特化会导致定义实际函数(而不仅仅是模板)。该定义将在每个翻译单元中出现,因此如果单独编译template_test.cpp
和main.cpp
,则函数的定义将包含在两个目标文件中,从而在链接时导致多重定义错误(因为它违反了ODR,即单一定义规则。
最好通过在类模板定义中包含函数定义(通过专门化int
的整个类模板)或使用关键字inline
来避免这种情况:
template<>
inline void mytest<int>::method(int input)
{
cout << "ok" << endl;
}
第二个问题是由于必须始终在使用模板专门化之前声明模板特化:
(14.7.3 / 6)如果一个模板,一个成员模板或一个类模板的成员被明确专门化,那么该特化应该在第一次使用该特化之前声明,这将导致隐式实例化,在发生这种用途的每个翻译单位;无需诊断。如果程序没有为显式特化提供定义,并且特殊化的使用方式会导致隐式实例化或成员是虚拟成员函数,则程序格式错误,无需诊断。永远不会为已声明但未定义的显式特化生成隐式实例化。 [...]
由于您的main.cpp
包含头文件,而不包含.cpp文件,因此在main.cpp
中使用模板特化时,不知道模板特化的声明。您可以通过在头文件中包含特殊化来解决这个问题,或者在类模板定义中(通过专门化int
的整个类模板),或者在类模板定义之外使用关键字inline
。 / p>
答案 1 :(得分:0)
你先问第二个问题。使用模板时请记住规则。不要将模板实现与cpp文件分开。将它们全部放在一个.h文件中。
你的第一个代码编译好我的VC2012,我不确定VC2013有什么问题。