C++模板的声明和实现

一、介绍

C++中,普通函数的声明和实现通常分别写在.h和.cpp中,但模板的声明和实现必须写在同一份文件中,否则编译会报错。

二、原理

C++的编译可以分为4个过程:预编译、编译、汇编和链接。对于普通函数,声明写在.h中,在预编译过程中,.h文件中的内容会被插入带对应的#include指令所在位置。在编译过程中,每个.cpp文件均会单独编译成二进制文件,如果此时调用函数的.cpp文件中找不到函数定义,那么就会将其标记为未解决符号(unresolved symbol)。在链接过程中,再整合解决符号引用问题。

// add.h
// 在预编译阶段,分别插入到add.cpp和main.cpp中
#ifndef _ADD_H_
#define _ADD_H_
int add(int a, int b);
#endif

// add.cpp
// 在编译阶段,会生成二进制文件add.o
#include "add.h"
int add(int a, int b) {
	return a + b;
}

// main.cpp
// 在编译阶段,会生成二进制文件main.o,并且在add函数的符号是未解决符号
// 在链接阶段,通过符号表解决add函数的符号问题
#include "add.h"
#include <iostream>
int main() {
	std::cout << add(1, 2) << std::endl;
	return 0;
}

而对于模板来说,模板的具体实例化一般并不会在代码中书写,因此模板的实现并不会生成二进制文件(因为没有实例化)。模板的实例化是在编译过程中,编译器预见模板使用时才会进行,如果此时.h文件中只有声明没有实现,那么编译器就无法正常实例化,则出现编译错误。

// add.h
// 声明和实现在同一文件中,也可以是.cpp或.hpp
#ifndef _ADD_H_
#define _ADD_H_
template <typename T>
class Add {
public:
    T add(T a, T b);
};
template <typename T>
T Add<T>::add(T a, T b) {
    return a + b;
}
#endif

// main.cpp
// 在编译阶段,编译器会在调用出实例化,即参考add.h生成Add<int>的具体代码
#include "add.h"
#include <iostream>
int main() {
    Add<int> s;
    std::cout << s.add(1, 2) << std::endl;
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值