我不知道这是否真的可能,但我试图以 map 向量的形式表示字段可视化,其中每个位置分配一个不同的键,对于每个键位置,它将存储一个类值,在我的例子中,该值可能是植物类或动物类,但我只是想先尝试以简单的方式实现它,所以说整数。这是我的.cpp:
#include "Grid.h"
#include <iostream>
using namespace std;
#include <string>
#include <vector>
#include <map>
template <class T>
Grid<T>::Grid(int grid_width, int grid_height){
cout<<"hello";
this->grid_width = grid_width;
this->grid_height = grid_height;
for (int h = 0; h < grid_height; ++h) {
map<string, T> row;
for (int w = 0; w < grid_width; ++w) {
char row_char = 'A' + h;
string code;
if (w>9){
code ="0";
}
else{
code="";
}
string key = row_char + code + to_string(w + 1);
row[key] = T();
}
grid.push_back(row);
}
}
template <class T>
int Grid<T>::getWidth() const {
return grid_width;
}
template <class T>
int Grid<T>::getHeight() const {
return grid_height;
}
template <class T>
T Grid<T>::getElement(const string& landId) const {
for (const auto& row : grid) {
auto it = row.find(landId);
if (it != row.end()) {
return it->second;
}
}
}
template <class T>
void Grid<T>::showGrid() const {
for (int w = 0; w < grid_width; ++w) {
cout << "+------";
}
cout << "+" << endl;
for (int h = 0; h < grid_height; ++h) {
for (int w = 0; w < grid_width; ++w) {
cout << "| ";
char row_char = 'A' + h;
string key = row_char + (w < 9 ? "0" : "") + to_string(w + 1);
auto it = grid[h].find(key);
if (it != grid[h].end()) {
cout << it->first;
} else {
cout << "____";
}
cout << " ";
}
cout << "|" << endl;
for (int w = 0; w < grid_width; ++w) {
cout << "+------";
}
cout << "+" << endl;
}
}
标题为:
#ifndef GRID_H
#define GRID_H
#include <iostream>
#include <vector>
#include <map>
#include <string>
template <typename T>
class Grid {
private:
std::vector<std::map<std::string, T>> grid;
int grid_width;
int grid_height;
public:
Grid(int grid_width, int grid_height);
int getWidth() const;
int getHeight() const;
T getElement(const std::string& LandId) const;
void showGrid() const;
};
#endif // GRID_H
我试图在我的 main 中这样调用它:
#include <iostream>
#include "Entity/Grid/Grid.h"
using namespace std;
int main() {
Grid<int> test(5,5);
test.showGrid();
return 0;
}
我得到的错误是
/usr/bin/ld: /tmp/ccZbVtb7.o: in function `main':
main.cpp:(.text+0x2e): undefined reference to `Grid<int>::Grid(int, int)'
/usr/bin/ld: main.cpp:(.text+0x3a): undefined reference to `Grid<int>::showGrid() const'
collect2: error: ld returned 1 exit status
我不明白,我认为模板应该涵盖所有形式的课程?
当您将类模板的声明放在头文件中,并将成员函数定义放在单独的
.cpp
中时,编译器在遇到仅包含头文件的文件中使用模板时无法实例化该模板.
发生这种情况时,编译器仍然可以从模板分配对象,因为它知道其各个成员的大小。它还可以编译对其任何成员函数的调用,因为它具有它们的签名。但是,它无法提供任何这些函数的地址。因此,它假设某处的
.cpp
文件包含这些函数的定义,并且当编译该文件时,链接器将能够插入各种函数调用的地址。
当然,这就是编译器对任何外部定义的函数所做的事情。
当编译器开始编译类模板的
.cpp
时,出现了问题。文件中没有任何内容告诉它为任何特定类型实例化类T
。因此,它不会实例化模板。当链接器寻找函数定义时,却找不到。
解决此问题的一种方法是使用显式实例化。
以下示例实例化类型
Grid
的类模板 T
为 int
。请注意,语法与模板专业化所用的语法类似,但关键字 template
后面没有空尖括号。
template Grid<int>; // "explicit instantiation"
如果您将其作为文件的最后一行
Grid.cpp
,您的程序将运行。
另一种方法是在头文件的模板定义中定义所有成员函数。那么你就不需要显式实例化。