关于C++ template 的初始化

新手可能会遇到编译没问题,自己写的模版类, 把声明(头文件.h)跟实现(cpp)分开, 编译时包括了模版的头文件, 编译没问题, 但连接不通过...是因为,如果你编译的代码模块中没用到那模版类的话, 它是不会帮你实例化的...而在另一个编译好的obj文件要用到模版类的时候, 会提示找不到那个符号..解决办法是需要你手动实例一个你将要用到类,  或者把模版的实现跟声明都在同一个文件
解决办法详见下文..

 Templates do not exist! (there is no spoon)

•Templates are a preprocessor construct.  They are cookie-cutters with which the preprocessor generates real C++ code.  When a template is used, (that is, specialized, implicitly or explicitly), it getinstantiated.

•The instantiation tells the preprocessor to create a version of the template where each placeholder is replaced by its specialization.  At this point, the specific version of the template comes into existence and can be compiled.  It does not exist otherwise!

•In a very real way, a template just does a search and replace for each type you specialize the template for.  In essence, you are doing the same as writing a bunch of overloaded functions.  It’s just done for you, behind your back.

Here, the template has been implicitly specialized by its context.  It is within the specialization region of the class scope.  Thus it does not need the template arguments. For a class definition, the specialization region is the class block.


Notice that the specialization

region does not include the return type.  Thus the return type needs explicit specialization.

Remember that though constructors and destructors have the same name as  the class template, they are functions and do not need to be specialized.

Problem

Templates do not exist until you use them.  They must be instantiated.  Unless this is done explicitly, instantiation occurs at the first usage for all known template definitions.  Thus, consider this example.  Compile with

g++ -Wall –ansi main.cc Matrix.cc

   /* main.cc */

#include 
< iostream >

using   namespace  std;

#include “Matrix.h”

int  main( void {

   Matrix
<int> m1(3,4);

   cout 
<< m1.getRows() << endl;

 }
  

Looks innocent, but it won’t link

Quiz: What won’t link and why?


The link error happens with m1.getRows() 

Nothing from a template gets instantiated until it is either used or explicitly instantiated.  • Matrix<int>::getRows() const does not get created until it is used at the line with m1.getRows().  The definition of the function is in Matrix.cc and never used there. Thus the definition never gets created and compiled to object code.  

Note: The compile line is actually wrong!

The file Matrix.cc only contains template code.  Since it is never used, it never generates object code and shouldn’t be compiled.

************************************************ 

There are three conventions to avoiding the link problem  

•Write all the code inline in the .h files.

•Do the same as above, but kind of fake it by writing an implementation file with your implementation and #include the implementation file in your header file.

•Write the template as you would a normal class (using a header and an implementation file).  Then create a new source file and #include the template implementation file there.  This is the file which you compile, not the template implementation.  (See next slide for example)

  The first two methods have the problem that anytime an implementation of a function is changed, all code that uses it must be recompiled (not just relinked).  This is very slow on large builds.  Also, the build process will instantiate the template many more times than necessary which is a waste of time and space.  The third method is free from such problems.  It also avoids some other hurdles since it forces the instantiation of everything at one point.

  

compile line:

g++ –Wall –ansi main.cc MatrixInst.cc 

/* main.cc */

#include 
< iostream >

using   namespace  std;

#include 
< Matrix.h >

int  main( void {

   Matrix
<int> m1(3,4);

   cout 
<< m1.getRows() << endl;

}


/* MatrixInst.cc */

#include “Matrix.cc”  

template Matrix
< int >    

//   notice that the  implementation (not header) file is included




The proper procedure

•Write the template, separated into a header and an implementation file

•Create an instantiation file for the template which include the implementation file.

•Compile the instantiation file and not the template implementation file.

•The instantiation file generates the object code for the template.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值