关于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::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.

你可能感兴趣的:(C++)