在c++中如何在地图向量中定义模板

问题描述 投票:0回答:1

我不知道这是否真的可能,但我试图以 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

我不明白,我认为模板应该涵盖所有形式的课程?

c++ templates vector
1个回答
0
投票

当您将类模板的声明放在头文件中,并将成员函数定义放在单独的

.cpp
中时,编译器在遇到仅包含头文件的文件中使用模板时无法实例化该模板.

发生这种情况时,编译器仍然可以从模板分配对象,因为它知道其各个成员的大小。它还可以编译对其任何成员函数的调用,因为它具有它们的签名。但是,它无法提供任何这些函数的地址。因此,它假设某处的

.cpp
文件包含这些函数的定义,并且当编译该文件时,链接器将能够插入各种函数调用的地址。

当然,这就是编译器对任何外部定义的函数所做的事情。

当编译器开始编译类模板的

.cpp
时,出现了问题。文件中没有任何内容告诉它为任何特定类型实例化类
T
。因此,它不会实例化模板。当链接器寻找函数定义时,却找不到。

解决此问题的一种方法是使用显式实例化

以下示例实例化类型

Grid
的类模板
T
int
。请注意,语法与模板专业化所用的语法类似,但关键字
template
后面没有空尖括号。

template Grid<int>;  // "explicit instantiation"

如果您将其作为文件的最后一行

Grid.cpp
,您的程序将运行。

在类模板中定义函数

另一种方法是在头文件的模板定义中定义所有成员函数。那么你就不需要显式实例化。

© www.soinside.com 2019 - 2024. All rights reserved.