类模板的分离编译-创新互联

一直觉得模板类是特别神奇的东西,它可以构造出不同类型的对象,使代码更加的灵活。这个过程就是类模板的实例化。

成都创新互联成立以来不断整合自身及行业资源、不断突破观念以使企业策略得到完善和成熟,建立了一套“以技术为基点,以客户需求中心、市场为导向”的快速反应体系。对公司的主营项目,如中高端企业网站企划 / 设计、行业 / 企业门户设计推广、行业门户平台运营、成都App定制开发手机网站制作设计、微信网站制作、软件开发、服务器托管等实行标准化操作,让客户可以直观的预知到从成都创新互联可以获得的服务效果。

 我们使用类的模板写一个stack类:

#include<assert.h>
#include"Seqlist1.h"
using namespace std;
template<class T,template<class> class Container  = Seqlist>
class Stack
{
public:
	void Push(const T& x)
	{
		_con.Pushback(x);
	}
	void Pop()
	{
		_con.Popback();
	}
	bool Empty()
	{
		return Size() == 0;
	}
	size_t Size()
	{
		return _con.Size();
	}
	T& Top()
	{
		size_t size = Size();
		assert(size > 0);
		return _con[size - 1];
	}
	void print()
	{
		_con.Print();
	}
	T& operator[](size_t index)
	{
		return _con[index];
	}
protected:
	Container _con;
};

 其中我们可以传入不同类型的T,class Continer是类型T的一个容器,这里默认是用自定义的一个顺序表来当容器。编译器就会构造出不同的代码出来。

 这样的实现方式是在类内定义成员函数,并把整个类放在.h中,这种方式叫做类模板的包含模式。这样的定义方式是有好处的,要使用Stack这个类,只要在头文件内包含类体就可以了,编译器很容易就可以找到类的定义。当然这种方式是有弊端的,如果一个类的成员函数个数很多并且很复杂,无疑在你去阅读或者修改定义的时候会让人很头疼,不能快速找到成员函数的定义。

 还好C++提供了另外一种方式——将成员函数的声明放在类体内.h中,将函数的定义放在.cpp中,就相当与类外定义,我们把这种方式叫做类模板的分离模式。这样写出来的代码是很美观的,并且易于修改。

//.h文件
#include<assert.h>
#include"Seqlist1.h"
using namespace std;
template<class T,template<class> class Container  = Seqlist>
class Stack
{
public:
	void Push(const T& x);
	void Pop();
	bool Empty();
	size_t Size();
	T& Top();
	void print();
	T& operator[](size_t index);
protected:
	Container _con;
};

//.cpp文件
//类外定义

template<class T,template<class> class Container  = Seqlist>
void Push(const T& x)
{
_con.Pushback(x);
}


template<class T,template<class> class Container  = Seqlist>
void Pop()
{
_con.Popback();
}

template<class T,template<class> class Container  = Seqlist>
bool Empty()
{
return Size() == 0;
}

template<class T,template<class> class Container  = Seqlist>
size_t Size()
{
return _con.Size();
}

template<class T,template<class> class Container  = Seqlist>
T& Top()
{
size_t size = Size();
assert(size > 0);
return _con[size - 1];
}

template<class T,template<class> class Container  = Seqlist>
void print()
{
_con.Print();
}

template<class T,template<class> class Container  = Seqlist>
T& operator[](size_t index)
{
return _con[index];
}

 类模板的分离模式就会牵扯出一些问题,比如说编译器在构造对象的时候它怎么找函数的定义的,因为函数的定义是在.cpp文件中的。这就是类模板的分离编译问题

 假设我们stack类是放在stack.h中的,成员函数的定义放在stack.cpp中的,然后类的调用放在main.cpp中,并且在main.cpp中包含了stack.h。

 按照我们通常的思路:

  • 编译main.cpp时,编译器不知道f(f是成员函数中的任意一个函数)的实现,所以当碰到对它的调用时只是给出一个指示,指示连接器应该为它寻找f的实现体。这也就是说main.obj中没有关于f的任何一行二进制代码。

  • 编译test.cpp时,编译器找到了f的实现。于是乎f的实现(二进制代码)出现在test.obj里。

  • 连接时,连接器在test.obj中找到f的实现代码(二进制)的地址(通过符号导出表)。然后将main.obj中悬而未决的call XXX地址改成f实际的地址,pofect。

但是当你编译的时候,编译器就会报链接错误,找不到成员函数的定义。说明我们的思路是错误的。对于模板,在没有实例化出对象之前是不会被编译成二进制代码的,而实例化是在程序运行的时候(也就是用到模板的时候)才实例化出对象,实例化是在编译器对代码进行编译的后面才发生的。这样问题就迎刃而解了,我们得手动的在main中包含.cpp文件,让编译器知道有函数的定义,这样编译器就不会报错了。

这里有必要提醒(总结)一下的是

  • 如果你的类不是用模板实现的,就不会有分离编译的问题,也就是说,即使你的类的成员函数是在类外定义的也不用include .cpp文件,不管你用没用到都会实例化出代码出来,就会编译成二进制文件,在链接时就会链接起来。

  • 如果你的类是模板类,并且想要在类外定义成员函数,就必须include .cpp文件。

另外有需要云服务器可以了解下创新互联scvps.cn,海内外云服务器15元起步,三天无理由+7*72小时售后在线,公司持有idc许可证,提供“云服务器、裸金属服务器、高防服务器、香港服务器、美国服务器、虚拟主机、免备案服务器”等云主机租用服务以及企业上云的综合解决方案,具有“安全稳定、简单易用、服务可用性高、性价比高”等特点与优势,专为企业上云打造定制,能够满足用户丰富、多元化的应用场景需求。

分享文章:类模板的分离编译-创新互联
标题路径:https://www.cdcxhl.com/article20/dpgsjo.html

成都网站建设公司_创新互联,为您提供微信小程序定制网站关键词优化网站制作网站建设网站设计公司

广告

声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联

小程序开发