C++中的模板不支持分离编译

C++中的模板不支持分离编译

 

 

按照我们之前的习惯,写出的代码是这样的

// Template.h
#pragma once
#include <stdio.h>
#include <iostream>
using namespace std;


int Add(int a,int b);//对普通函数的声明

template<class T>
T Sub(T a,T b);//对模板函数的声明
//Template.cpp
#include "Template.h"

int Add(int a,int b)//普通函数的定义
{
    return a+b;
}

template<class T>

T Sub(T a,T b)//模板函数的定义
{
    return a-b;
}
//test.cpp 
#include "Template.h"


int main()
{
    cout<<"ret_1:"<<Add(1,2)<<endl;
    
    cout<<"ret_2:"<<Sub(3,6)<<endl;
    return 0;

}

#pragma once
#include <stdio.h>
#include <iostream>
using namespace std;


int Add(int a,int b);//对普通函数的声明

template<class T>
T Sub(T a,T b);//对模板函数的声明
//Template.cpp
#include "Template.h"

int Add(int a,int b)//普通函数的定义
{
    return a+b;
}

template<class T>

T Sub(T a,T b)//模板函数的定义
{
    return a-b;
}
//test.cpp 
#include "Template.h"


int main()
{
    cout<<"ret_1:"<<Add(1,2)<<endl;
    
    cout<<"ret_2:"<<Sub(3,6)<<endl;
    return 0;

}
 

Makefile文件是这样写的:

a.out:Template.cpp test.cpp                                                                                                                                  
    g++ -g -o $@ $^
.PHONY:clean
clean:
    rm -f a.out

我们进行编译后发现:

 

说未定义的Sub函数,我们这里的Add函数其实是和Sub函数一样定义与声明分离的,Add函数并没有报错

 

如何解释这种现象:

 

当编译器对test.cpp文件进行编译时,在展开的头文件中只找到了Add()函数和Sub()函数的声明,并没有找到其定义。

这里的call指令后面的地址是缺省的(可以先这样理解)

在链接这一步骤时,Add函数的定义会在template文件中找到

其实着函数其实是用函数名在符号表中去找对应的函数名和对应的地址

根据上面的编译结果来看,Add函数的定义是找到了,那么为什么Sub函数没有找到呢?

我们之前讲过,函数模板只有在实例化后才会生成相应的代码,从这一点来看

template.cpp文件中只是有模板函数的定义,并没有实例化模板参数,所以编译时并没有生成代码

Sub函数也不会出现在符号表中,在链接找不到Sub函数的定义,就会出现链接错误。

 

综上所述:所以模板是不支持分离编译的

 

那么如何解决这个问题呢:

1.模板参数实例化

// Template.h

#pragma once

#include <stdio.h>

#include <iostream>

using namespace std;

int Add(int a,int b);//对普通函数的声明

template<class T>T Sub(T a,T b);//对模板函数的声明


//Template.cpp

#include "Template.h"

int Add(int a,int b)//普通函数的定义
{
    return a+b;
}

template<class T>

T Sub(T a,T b)//模板函数的定义
{
    return a-b;
}

//模板参数实例化 template int Sub<int>(int,int); //test.cpp

#include "Template.h"
int main()
{
    cout<<"ret_1:"<<Add(1,2)<<endl;
    cout<<"ret_2:"<<Sub(3,6)<<endl;
    return 0;

}

这样在template.cpp文件中就会生成Sub函数的代码

但是如果有不同的实例类型,那就需要一个一个进行参数实例化,所以说这种方法并不是很好

2.在test.cpp文件中也包含一下template.cpp文件

这样template.cpp文件就会在test.cpp文件中进行展开,其实这样的话,我们根本不需要在头文件中对函数进行声明了,但是这种方法如果你在别的项目中要用的话,就要除了包含template.h文件还要包含其函数的定义文件template.cpp文件.

 

3.其实更好的实现就是,不要将模板函数声明和定义分离

最好是写在一个.h(或者是.hpp文件)文件中,上面放函数的声明(方便查找),下面放函数的定义

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值