初识c++(36)之模板函数与分离编译模式

分离编译模式

一个程序(项目)由若干个源文件共同实现,而每个源文件单独编译生成目标文件,最后将所有目标文件连接起来形成单一的可执行文件的过程称为分离编译模式。

举个例子:

//main.cpp
#include <iostream>
#include "hello.h"

int main(int argc, char** argv) {
	my_function(1);
	return 0;
}
//hello.cpp
#include<iostream>

void my_function(int t)
{
	std::cout << t << std::endl;
}
//hello.h
#ifndef HELLO_H
#define HELLO_H

void my_function(int t);

#endif

上面这些文件的编译文件的大致过程是这样,两个cpp是分开独立进行编译的。main.cpp会被编译成一个main.o的目标文件,虽然这时候并不知道my_function()的内容是什么,但是由于添加了hello.h这个头文件,就会知道这是一个外部的函数,编译器就会做一个暂时性的处理。hello.cpp会被编译成一个hello.o的目标文件。然后就是一个链接的过程,main.o就会链接hello.o文件生成一个main.exe(或者main.out)的可执行文件,在这个链接过程中,main.o中的my_function()函数就会在hello.o中找到函数实体,从而链接成功。

模板函数在分离编译模式下的失效

将上面的函数改模板函数:

//main.cpp
#include <iostream>
#include "hello.h"

int main(int argc, char** argv) {
	my_template_function(1);
	return 0;
}
//hello.cpp
#include<iostream>
template<class T>
void my_template_function(T t)
{
	std::cout << t << std::endl;
}
//hello.h
#ifndef HELLO_H
#define HELLO_H

template<class T>
void my_template_function(T t);

#endif

模板函数的特性就是只有对模板函数进行了实例化,模板函数才会被展开。比如上面的例子,hello.cpp在被编译成hello.o的过程中,并不知道void my_template_function(T t);函数的模板参数是什么类型,所以这个模板函数也没有被展开。在链接的过程中,main.o找不到my_template_function<int>(int);这个函数,所以就会找不到函数链接而报错。

解决办法(C++永远的痛)

1、export

在函数定义时加上关键字export,就可以解决这个问题,但是这会要求编译器做很多工作,各大编译器也都不支持这个功能,只有少部分编译器使用这个功能,所以C++11这个关键字只是被保留,功能也被弃用了。

2、显示模板函数实例化

只需要在hello.cpp文件中加上一句:

//hello.cpp
#include<iostream>
template<class T>
void my_template_function(T t)
{
	std::cout << t << std::endl;
}

template void my_template_function<int>(int t);

这带来的问题就是,模板函数就失去了模板函数的意义,如果我事先就已经知道了模板函数的参数类型,用函数重载就可以搞定了。之所以使用模板函数就实现不知道类型参数。

3、将模板函数的定义放在头文件中

只需要修改hello.h

//hello.h
#ifndef HELLO_H
#define HELLO_H

template<class T>
void my_template_function(T t)
{
	std::cout << t << std::endl;
}

#endif

这样做之所以能成功,是因为,我们在main.cpp文件中添加了hello.h,在预处理阶段头文件是会被展开在main.cpp中的,其实这样写,跟直接将模板函数写在main.cpp中是没有本质却别的,接下来编译main.cpp,由于main.cpp中使用了my_template_function<int>(int);,所有模板函数就会被实例成功。

很明显这样就破坏了C++优雅的分离编译的优雅性,成为了C++永远的痛。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值