c++在模板实战前你不得不了解的事:包含模型

本文探讨了模板代码与非模板代码在面向对象编程中的区别,指出模板代码需要在使用时实例化,导致编译器在不同文件中可能出现无法解析的问题。通过一个具体的例子,解释了在Visual Studio 2019中遇到的编译错误。为解决此问题,提出了将模板函数声明与实现放在一起的解决方案,尽管这可能不符合传统的面向对象编程风格。文章建议使用预处理器指令来避免某些缺点,同时提醒读者这种方式可能导致代码提示丢失。
摘要由CSDN通过智能技术生成

在前面,我用各种容器实现过stack容器.也说了一些关于模板的基础知识.现在,我想更为深入,系统的谈谈模板代码与普通代码的区别.

首先,在面向对象编程中(注意:模板严格来说已经不属于面向对象编程了,它属于泛型编程)你看能会这么组织自己的非模板代码(这也是我推荐大家能养成的编程习惯):

  • 类和其他类型被放在头文件中.通常来说,头文件是一个扩展名为.hpp(或者.H .h .hh .hxx)的文件.
  • 对于(非内联)函数和全局变量,只有声明在头文件中,定义在dot-C文件中.通常而言,dot-C文件是扩展名为.cpp(或者 .C .c .cc .cxx)的文件.

这样一切就可以正常运行了,这样写也很好,我也很推荐.但是,当我们习惯了面向对象编程再转到泛型编程时你总是会感到很崩溃.甚至于你可能都不知道编译器为什么会出错,明明你写的语法没有任何问题!

举例:

头文件func.h

#ifndef __FUNC__
#define __FUNC__

//头文件里的函数声明
template<typename T>
void func(T const&);

#endif // !__FUNC__

头文件func.h的实现

#include "func.h"
#include <iostream>

template <typename T>
void func(T const&) {
	std::cout << "我什么也不想做" << std::endl;
}

测试

#include <iostream>
#include "func.h"


int main()
{
	func(10);

	return 0;
}

如果你跟我一样使用的是visual studio 2019的话,编译器会在你尝试运行时报错.报错的意思大概是:对于func(10)这个函数的调用无法解析.换句话来说,编译器不认识这个东西.What!???你可能会莫名其妙.

实际上,这根模板的特点有关:那就是在这个文件中我被用到了我就实例化(这种实例化是自动的,编译器帮你干了),不然就不管它当它不存在.编译器想认识一个函数,那么这个函数就必须实例化,由于每个文件是单独编译的.在func.cpp文件中,编译器一看.嗯......这是一个模板函数的实现但这个模板并没有被谁用到,那么我就不要它了,然而在func.h文件中的情况是,嗯.....这是一个模板函数的声明,嗯......实现不在这里,嗯.......可能在其他地方,待会儿再看看.所以,你一到使用这个函数的时候,编译器就会说,这个模板函数只有声明,没有实现,无法解析.(注意:我上面的解释并不专业,我只是往理解性的方向说,因为要说明白什么是模板实例化,原理是什么,什么是链接器,它是干什么的,感觉又要好几篇才能说清楚,感兴趣的话,可以自己去了解了解.)

那么怎么办呢?

最有效的办法就是,声明实现放一起.(称为包含模型)

但是,你可能会感觉到十分不舒服.因为,你可能更像让它接近面向对象编程的那种感觉.

那么我目前建议你这么做:

//头文件func.h
#ifndef __FUNC_H__
#define __FUNC_H__

//头文件里的函数声明
template<typename T>
void func(T const&);

#define __FUNC_CPP__
#include "func.cpp"

#endif // !__FUNC


//实现文件func.cpp
#ifdef __FUNC_CPP__

#include <iostream>

template <typename T>
void func(T const&) {
	std::cout << "我什么也不想做" << std::endl;
}

#endif

当然,这么做并不是那么的完美,如果你自己去打一遍你就会发现显而易见的缺点(没有代码提示).这里我也不想去解释各种预处理器指令的作用了,因为这不是我这篇文章的重点.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值