C++模板类编程的链接问题

本文通过一个具体的模板类实例化案例,详细分析了C++中模板实例化的机制及常见错误原因,并提供了解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

问题引入

前两天想写一个模板类,里面放一些编程的时候常用的函数,比如动态创建二维数组。下面是我一开始写的代码:

//templateLibrary.h
 #include <exception>
 template <class T>
class arrayCommand
    {
    public:
        arrayCommand();
        ~arrayCommand();
        //二维数组构造
        bool make2dArray(T** &x, const int & numberOfRows, const int & numberOfColumns);
    private:
    };
--------------------------------------------
//templateLibrary.cpp
#include "stdafx.h"
#include "templateLibrary.h"
#include <iostream>

template <class T>
arrayCommand<T>::arrayCommand() {}

template <class T>
arrayCommand<T>::~arrayCommand()   {}

//二维数组构造
template <class T>
bool arrayCommand<T>::make2dArray(T** &x, const int & numberOfRows, const int & numberOfColumns)
    {// Create a two dimensional array.
        try {
            // create pointers for the rows
            x = new T *[numberOfRows];

            // get memory for each row
            for (int i = 0; i < numberOfRows; i++)
                x[i] = new int[numberOfColumns];
            return true;
        }
        catch (std::bad_alloc) { return false; }
    }
------------------------------------------------
//test.cpp
#include "templateLibrary.h"
#include <iostream>
int main()
{
    int** a;
    arrayCommand<int> *arrCommand = new arrayCommand<int>;
    arrCommand->make2dArray(a, 2, 2);
    a[0][0] = 1;
    a[0][1] = 2;
    a[1][0] = 3;
    a[1][1] = 4;
    std::cout << a[0][0] << ' ' << a[0][1] << std::endl;
    std::cout << a[0][0] << ' ' << a[1][1] << std::endl;
    system("pause>>null");
    return 0;
}

这段代码是不能够正确运行的,编译器会报出一个符号在main函数中被引用的错误。
这里写图片描述
使用gdb逐语句进行调试,一开始就会报错,可以判定这段代码实在程序运行之前有问题,在网上查阅了error LNK2019,发现是链接的问题。
为解决这个问题,就要深入的理解模板实例化。

问题分析

C++中模板的实例化指函数模板(类模板)生成模板函数(模板类)的过程。对于函数模板而言,模板实例化之后,会生成一个真正的函数。而类模板经过实例化之后,只是完成了类的定义,模板类的成员函数需要到调用时才会被初始化。

在上面的例子中,arrayCommand是一个模板,但是并不是一个类型,而arrayCommand<int>是一个模板实例,是一个类型。所以,从arrayCommand 创建arrayCommand<int>实例的过程就是模板的实例化过程。
首先,在编译阶段,编译器需要创建一个arrayCommand<int>类型,当编译器编译templateLibrary.cpp的时候,因为不知道模板arrayCommand 的参数,故不能生成模板类的成员函数的代码;当编译器编译templateLibrary.h的时候,明确了模板arrayCommand 的声明,但是在此文件中没有找到模板的定义,所以在编译阶段不能够生成类型arrayCommand<int>,但是此时并不会报错,因为编译器可能认为类型arrayCommand<int>的定义在其它的文件中,所以就交给之后的链接程序处理。

在链接阶段,我们需要找到arrayCommand<int>的定义,但是在编译阶段并没有生成成员函数的代码,所以,找不到相应的定义,就会报出上述的错误。

问题解决

分析过问题的原因之后,这个问题就迎刃而解了,我们知道在编译阶段编译器在templateLibrary.h中找不到arrayCommand<int>的定义,所以只要将templateLibrary.cpp中的内容添加至在templateLibrary.h中即可。
经验证,这种方法可以解决此问题。
这里写图片描述

注:本篇博客部分参考了http://blog.youkuaiyun.com/onafioo/article/details/29857281,原博客中作者给出了另外的解决方法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值