这段代码有什么问题:
标题:
#include <map>
using namespace std;
template<class T>
class ValueCollection
{
public:
ValueCollection(void);
int getValueCount(void);
map<string, T> Values;
};
实现:
#include "ValueCollection.h"
ValueCollection<class T>::ValueCollection(void)
{
}
int ValueCollection<class T>::getValueCount(void)
{
return Values.size();
}
测试:
#include "ValueCollection.h"
TEST(ValueCollection_TestCases, Default_Constructor_MapIsEmpty)
{
ValueCollection<int>* target = new ValueCollection<int>;
int expected = 0;
int actual = target->getValueCount();
ASSERT_EQ(expected, actual);
}
这是错误:
Error 1 error C2079: 'std::_Pair_base<_Ty1,_Ty2>::second' uses undefined class 'T' c:\program files (x86)\microsoft visual studio 10.0\vc\include\utility 167 1 Refactor01
最佳答案
几个问题。
最直接的编译器错误是由类模板成员函数实现中的语法错误引起的。您必须在类模板成员的定义前加上 template
关键字。即:
template<class T> ValueCollection<T>::ValueCollection(void)
{
}
template<class T> int ValueCollection<T>::getValueCount(void)
{
return Values.size();
}
还有另一个问题,随着程序的增长,这个问题只会在以后变得明显。您不能在一个文件中定义模板函数或类 Translation Unit并在其他地方使用它们。编译器必须在每个翻译单元中提供完整的定义。
通常,实现这一点的方法是直接在头文件中定义模板函数,就在它们被声明的地方。在你的情况下:
template<class T>
class ValueCollection
{
public:
ValueCollection(void)
{
}
int getValueCount(void)
{
return Values.size();
}
map<string, T> Values;
};
这只是实现这一目标的一种方式——还有其他方式。另一种方法是使用所谓的“inclusion method”:
ValueCollection.h
template<class T>
class ValueCollection
{
public:
ValueCollection(void);
int getValueCount(void);
map<string, T> Values;
};
#include "ValueCollection.hpp:
ValueCollection.hpp
template<class T> ValueCollection<T>::ValueCollection(void)
{
}
template<class T> int ValueCollection<class T>::getValueCount(void)
{
return Values.size();
}
还有一种方法是为每个想要使用模板的翻译单元提供一个新的定义,但这非常不常见。 (事实上,在我 15 年的 C++ 编程生涯中,我从未这样做过)
关于带有映射声明的 C++ 模板参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8272097/