模板类声明和定义为何要写一起 – u012750314的博客

模板类声明和定义为何要写一起 – u012750314的博客

若何写原生的模板顺序
颁发日期: 1/21/2003 12:28:58 PM 
颁发人: Nemanja Trifunovic

通向
被问到设想常常运用的模板复杂的成绩,我的回复是:运用模板是容易地的,但它是不容易写。看一眼模板类,笔者近乎每天都能晤面。,如STL, ATL, WTL, 和做加法模板类,Can feel the taste:用电话与交谈话筒复杂,巧妙地控制复杂。

5年前我开端运用上面所说的事模板,当我领会诉讼MFC。直到上年,我都不的必要其写模板类。但我必要写其的类模板,我高音的尤指不期而遇的证书是国际公约的编程序方法(证明我,在*定义。cpp证明)不克不及用于模板。因而我花了稍许的工夫去相识和处理成绩。

上面所说的事对象是熟习的但过失很多的著述业经历的模板。本文只屈尊做某事模板类,不触及模板功用。但规律是平稳的的两。

成绩的产生
经过原生的建议来阐明上面所说的事成绩。诸如,证明装饰切中要害原生的模板类。:
//
template
class array
{
T data_[SIZE];
array (const array& 那个的)
const array& operator = (const array& 那个的)
public:
array(){};
T& 巧妙地控制符[ ](int i) { return data_[i];}
const T& get_elem (int i) const { return data_[i];}
void set_elem(int i, const T& 值) {data_[i] = value;}
operator T*() { return data_;}      
};            
之后次要功用运用上面的模板证明:
//
#i 包罗 “”

int 次要(void)
{
array intArray;
(0, 2);
int firstElem = (0);
int* begin = intArray;
}
当波湾阴谋和运转是有规律的的。程旭贤创立了原生的典型50个整数装饰,该装饰的第原生的元素,之后将值设置为2,之后读第原生的元素的值,对装饰的摄取点的操纵。

但设想用国际公约编程序方法来编辑会产生是什么呢?笔者来看一眼:

证明和增加发行成两个证明(不变的)
//         
template
class array
{
T data_[SIZE];
array (const array& 那个的)
const array& operator = (const array& 那个的)
public:
array(){};
T& 巧妙地控制符[ ](int i);
const T& get_elem (int i) const;
void set_elem(int i, const T& 值);
operator T*();      
};        
//
#i 包罗 “”

template T& array::operator [](int i)
{
return data_[i];
}

template const T& array::get_elem(int i) const
{
return data_[i];
}

template void array::set_elem(int i, const T& 值)
{
data_[i] = value;
}
template array::operator T*()
{
return data_;
}
3会产生波湾阴谋时翻转。成绩暴露了:
为什么翻转呈现时原生的的职位?
为什么仅仅3个环节出错?有4个会员功用。
为了回复在附近的成绩,笔者霉臭增进相识模板的建议化换异。

模板建议化
在模板类的最公共的的翻转是暂时运用的顺序员。典型限制因素(限制因素化 典型)术语通向念错。自然,无模板的标明典型,模板是原生的模板,正像它的名字:

  波湾阴谋器用模板,经过使不同模板限制因素创立原生的标明典型。上面所说的事换异是模板(建议化)。。
从模板类创立抓住的典型称之为特别表壳(specialization)。 
模板建议化依赖于波湾阴谋器找到构成疑问句和否定句的编码Cre,
point of 建议化)。
创立原生的特别的养护,波湾阴谋器不霉臭只领会模板的公务的,还要领会模板的定义。
模板建议化的换异是迟钝的,最好的用于定义真实证明某事属实的证据的功用。

回头一看上面的建议,笔者可以领会,装饰是原生的模板,array是原生的模板的建议 – 原生的典型。创立装饰的装饰换异的建议化换异。建议化元素表现时证明中。设想以国际公约的方法,波湾阴谋器会在证明模板的公务的,但无模板的定义,波湾阴谋器将无法创立原生的典型的装饰。但这是无错的,鉴于波湾阴谋器以为模板定义在其它证明中,成绩是衔接处置顺序。

现时,波湾阴谋时会产生什么成绩?波湾阴谋器可以解析模板,但不克不及产生会员功用指定遗传密码。它可以出示指定遗传密码,鉴于必要出示指定遗传密码,要获得模板限制因素,原生的典型的必要,而过失模板其。

异样,在顺序互连 或 未检出的打扮的定义,他说的无错的定义的会员。

这样,笔者回复第原生的成绩。但有二成绩,在功用中有4个会员,互连器为什么仅仅3的答案是错的吗?:对这一气象的惯量通向建议化。无巧妙地控制者的运用,波湾阴谋器还无定义建议化。

分解物
认得了成绩,笔者可以处理上面所说的事成绩:
在元素建议化并让波湾阴谋器领会模板定义。
用另原生的证明来显示建议化的典型,此互连将可以领会这种典型的。
运用export秘诀词。

前两种方法通常高地典型用土覆盖,第三种方法称为分岔榜样。

原生的种方法是运用模板替换证明时不应,还典型原生的模板定义证明。在上面的建议中,是第原生的建议,适合功用定义的接到会员功用。或许在证明中典型的证明。如下,波湾阴谋器可以领会模板的公务的和定义,打扮的长建议。这种方法的错误是波湾阴谋证明会长胖,敏锐的压下了波湾阴谋和衔接速率。

第二的种方法,显式模板建议化的典型可。最好将显式建议化都放在另原生的证明。在本例中,你可以创立原生的新的证明:
//                 
#i 包罗 “”

template class array ; // 显式建议化
array典型不克不及从事制造,但在从事制造。异样的互连可以找到它的定义。用这种方法,无原生的宏大的头证明,放慢波湾阴谋速率。和证明其的头越来越彻底,更具易读。但这种方法不克不及抓住的惯量建议化的净值利润率,它将清楚的地出示接到的会员功用。不计辩护证明。

第三种方法是在模板定义中运用export秘诀词,等等的人或物的事实让波湾阴谋器来处置。当我在
Stroustrup识别力口,感触很兴奋的。但很快就见VC 6不证实,后头又见基本的无波湾阴谋器可以证实上面所说的事秘诀词(第原生的证实它的波湾阴谋器要在2002岁暮年终才问世)。自那接近末期的,我看过很多文字在附近的输出,获得它可能性很难处理的成绩处理榜样。设想你想获得更多的秘诀词,当心事项国药 萨特的著述业。

收场白
利用原生的模板库,要获得模板类是过失同一的的原始性,运用那个的编程序思惟。本文的意图过失惊吓那想模板顺序。正相反,提示他们废止模板编程序时会呈现B。

//////////////////////////////

即便在非内联功用的定义,将接到的公务的和定义将模板的头证明。这如同与头证明的流通统治:外出把稍微设备空间的分派,上面所说的事统治是为了屯积衔接翻转的下有多个分社的旅行社定义。但模板的定义是很特别的。经过模板<...>稍微处置使基于波湾阴谋器不分派设备空间,它一向在准备妥财产,直到反应诉原生的模板建议。在波湾阴谋和互连的某方面。,有多个定义可以去除模板机制,因而,运用方便,不变的把接到的模板公务的和定义在头证明。

为什么不克不及证实的C 波湾阴谋器波湾阴谋模板分岔
刘伟鹏(pongba) /文

率先,C 规范中提到的,原生的波湾阴谋单元[诠释 unit]是指原生的.cpp证明与它所i包罗的接到.h证明,h证明里的指定遗传密码将会被拉长说到包罗在.cpp证明,之后波湾阴谋器波湾阴谋.cpp证明为原生的obj证明,后者有PE [携带式 Executable,Windows可获得性证明体式。,它一趟典型二元系指定遗传密码,而是,无法获得,鉴于不克不及保证书一定会有原生的次要功用。当波湾阴谋器将在波湾阴谋原生的使突出分岔后的CPP证明,衔接器(Linker)衔接成原生的.exe证明。 
举个建议: 
// 
void (f);//上面所说的事功用f
// 
#i 包罗”” 
void f() 

…//do something 
} 这一公务的在功用f
//—————————–// 
#i 包罗”” 
int main() 

f(); //行使f,F有原生的外接式

在上面所说的事建议中,测验。 cpp和各被波湾阴谋变成形形色色的的.obj证明[权且命名为和],在中,行使功用f,但是,当波湾阴谋器,它不只典型只获得在完全无用的证明 (f)公务的,因而,波湾阴谋器将在这里作为表面衔接典型,那是在另原生的功用的获得指定遗传密码的.obj证明,这异样证明某事属实的证据,更确切地说,中实在无在附近的f功用的纵然政党的二元系指定遗传密码,实在的指定遗传密码波湾阴谋。在行使f将出示原生的行使讲授,像异样: 
call f 【C 快速地流动的称呼停止混乱
在波湾阴谋的时分,CALL讲授显然是翻转的,鉴于有政党的指定遗传密码无获得F。笔者能做什么呢?这是衔接器的义务,衔接器正大光明在其它的.obj中[本例为]寻觅f的获得指定遗传密码,当行使 F行使该讲授地址到实在的f功用进入方法点地址。必要当心的是:衔接器实在全体的工程里的.obj“衔接”成了原生的.exe证明,这是最秘诀的义务是上面说的,寻觅另原生的表面衔接的典型。目的地址,之后,代替证明是的假。。 
设想上面所说的事换异增进: 
call 本讲授不,它实在上是同一的的连根拔出,这是原生的
jmp 0x23423[上面所说的事地址可能性是恣意的,但是,秘诀是要原生的命令的真正称为地址 F功能。更确切地说,的.obj证明外面的接到行使f快速转移到同原生的地址。,在后者的真的叫F。异样做的净值利润率执意衔接器修正地址时既然对后者的call XXX地址的使不同就行了。而是,衔接器是若何找到f的实在地址的呢[在本例中这在中],鉴于the.obj.exe体式是公正地的,上面所说的事证明的标志表和标志表[出口出口输出 table和export 表]切中要害接到标志和它们相互关系的地址。异样衔接器既然在的标志导出表中寻觅标志f[自然C++对f作了mangling]的地址就行了,之后稍许的偏移处置[鉴于两。Obj证明,自然会有稍许的使卷曲。,这清楚的的封面标志在衔接器拔出表F从事ITE。 
这是可能性的。秘诀是要: 
波湾阴谋时,波湾阴谋器不获得F的获得,接到当碰到对它的行使时无论如何抚养原生的通知,衔接器霉臭找到它的F讲授。这过失在附近的稍微线的二元系指定遗传密码F。 
波湾阴谋时,波湾阴谋器找到获得F。如下,在二元系指定遗传密码F [ ]切中要害获得。 
衔接时,经过标志表F ]在口找到衔接器指定遗传密码[二]地址[。之后在叫含糊不定 XXX地址到实在的F地址。 
填写。

但是,到某种状态模板,你获得的,,指定遗传密码的模板功用不立即波湾阴谋成二元系码,有原生的换异。举个建议: 
//—————-// 
template 
void f(T t) 
{} 
int main() 

…//do something 
f(10); //call f 波湾阴谋器决议给F F到处这里。与肢体
…//do other thing 

更确切地说,设想你不行使f的证明,F也得不到了,无上部位稍微F和二元系码!!设想你把这: 
f(10); //f为了获得。
f(); //f为了获得。
这将有原生的F,f二元系指定遗传密码段功用。等等。 
但是例示想要波湾阴谋器获得模板的定义,过失吗? 
见上面的建议:模板及其获得[ ]分岔
//—————————–// 
template 
class A 

public: 
void f(); 在这里无论如何原生的公务的
}; 
//—————————-// 
#i 包罗”” 
template 
void A::f() 模板的获得,但必要当心的是,:眼前,

…//do something 

//——————————// 
#i 包罗”” 
int main() 

A a; 
a. f(); 波湾阴谋器不获得在这里f的定义,鉴于它外出那边。
因而波湾阴谋器最好的祝福衔接器,我祝福它可以在other.obj。
//AF的获得,在上面所说的事建议中是,但是,后者是真的::f的 
二元系指定遗传密码无?!!!鉴于C 规范是清楚的的,当原生的模板时不运用
它会不会被裁员的侯,中用到了A无F?!!因而实 
在波湾阴谋的证明公司或企业的惹起::无F的二元系指定遗传密码
因而衔接器呆若木鸡,给你原生的翻转的衔接
//而是,设想你写原生的功用,盈利给原生的::f,波湾阴谋器将出,鉴于在这点上[中],波湾阴谋器获得模板的定义,因而现时/十足,终于,标志表导出上面所说的事标志F
//址,因而能填写义务。 
}

秘诀是要:在原生的独自的波湾阴谋事件,原生的波湾阴谋器波湾阴谋.cpp证明时不获得另原生的cpp证明在。,未检出的[当未决定的标志在祝福它将衔接。该用土覆盖在模板无任务,但当模板呆若木鸡,鉴于模板仅仅在必要的时分才会呈现。,因而,当波湾阴谋器领会仅仅模板公务的,它不克不及建议化模板,您最好的创立表面标志衔接和企T。但是,当不运用.cpp证明切中要害模板获得模板,波湾阴谋器是无意出去,因而,The whole project in.Obj can not find a template instantiation the binary co,衔接器还贵州

/////////////////////////////////
.NET/develop/article/19/19587.shtm
C 的模板指定遗传密码有组织的 典型榜样(典型 用土覆盖) 选择自 sam1111 的 Blog  
秘诀词   Template Inclusion Model 
出处   C++ Template: The Complete Guide

阐明:本文译自C Template: The Complete 第直觉章切中要害一本书。比来领会C 民众领袖上常常有原生的在附近的后模板榜样,社团初学者模板,到某种状态原生的近亲关系的成绩困惑,如下本文诠释,祝福对初学者有帮忙。

模板指定遗传密码有两三个形形色色的的有组织的,本文引见了一种最深受欢迎的原生的:典型榜样。

互连翻转

绝大多数C / C 顺序员这非模板指定遗传密码的有组织的:

         类和那个典型储藏处在头证明,这些头证明具有.hpp(或许.H, .h, .hh, 他们拉长说)。

         全程变量和(非内联功用),Only the declarations in header files,在C证明的定义,这些证明具有.cpp(或许.C, .c, .cc, cxx发挥)。

上面所说的事有组织的是举世无双的:它使得顺序可以容易地地增长所需的典型定义,废止衔接器变量或功用的反复的定义。

鉴于有组织的是你这么说的嘛!礼仪的星力,模板编程序的初学者常常犯异样的翻转。上面所说的事小顺序告发了上面所说的事翻转。像流通指定遗传密码,笔者定义到处头球模板:

// basics/ 

#ifndef MYFIRST_HPP 
#define MYFIRST_HPP 

// declaration of template

template

void print_typeof (T const&);

#endif // MYFIRST_HPP

print_typeof()公务的了原生的复杂的辅佐功用用来捣碎稍许的典型教训。C证明功用定义:

// basics/

#i 包罗

#i 包罗

#i 包罗 “” 

// implementation/definition of template

template  
void print_typeof (T const& x) 
{

    std::cout << typeid(x).name() << std::endl;

}

上面所说的事建议运用typeid巧妙地控制符来捣碎原生的字母行,这类教训提出异议字母行限制因素。

首要的,笔者用笔者的模板在原生的C证明,在文档模板公务的#我 包罗:

// basics/myfirst 

#i 包罗 “” 

// use of the template

int main() 
{

    double ice =  
print_typeof(ice);  // call function template for type double

}

绝大多数的C 波湾阴谋器(compiler)可能性会接到顺序,无稍微成绩,而是,互连器(linker)将谣言能力或方式翻转,(print_typeof)提示,功用定义的缺少。

这是翻转的导致,模板功用print_typeof()的定义还无被例示(instantiate)。为了建议化原生的模板,波湾阴谋器只好获得哪原生的霉臭被定义与使用现代方法,用什么来了现时的模板限制因素。三灾八难的是,在前面的建议,这两套教训依赖形形色色的的证明独自波湾阴谋。如下,当笔者领会print_typeof波湾阴谋器(用电话与交谈),但无领会眼前的功用定义的双型,它基本原理异样的定义想要了那个某方面,遵从的创立原生的定义(运用规范析像系数的互连)。在另一方面,当波湾阴谋器处置时,证明中无稍微迹象表白它只好是原生的特别的限制因素,。

在头球模板

上面所说的事成绩的处理方案是反击在附近的,该方法采取平稳的的宏和内联功用:笔者将模板的定义典型进公务的模板的头证明中。到某种状态笔者的示例,笔者可以用#我 包罗 添加到证明的末了,或典型在每个运用笔者的模板证明的证明,要经过努力到达某事物的意图。自然,有第三种方法,该证明将被截,重写证明,它典型接到模板的公务的和定义:

// basics/myfirst2.hpp

#ifndef MYFIRST_HPP 
#define MYFIRST_HPP 

#i 包罗  
#i 包罗  

// declaration of template 
template  
void print_typeof (T const&); 

// implementation/definition of template 
template  
void print_typeof (T const& x) 
{

    std::cout << typeid(x).name() << std::endl;

}

#endif // MYFIRST_HPP

上面所说的事有组织的的模板指定遗传密码的方法称为糅杂用土覆盖。这次健康状态后,You will find that we have been able to compile program、互连、家具。

笔者可以从上面所说的事方法的稍许的后果。最值当当心的若干是,,这种方法在一定程度上做加法本钱,包罗。在上面所说的事建议中,这种在头顶上是无定义的模板形成大块其,这是形成的证书。,笔者只好有笔者的模板运用的头证明,在上面所说的事建议中是。你会见,这通向了几万条指定遗传密码,鉴于如上面所说的事头证明还典型原生的模板定义和笔者公正地。

这确凿是原生的成绩的充分发挥潜在的能力。,鉴于它做加法了必要在获得波湾阴谋顺序的波湾阴谋。笔者将在上面的章节中证明稍许的那个可能性的分解物。但怨恨,实在全面的切中要害顺序花一小时来波湾阴谋互连一趟是快的了(笔者一趟尤指不期而遇过破费数天工夫来从源码波湾阴谋的顺序)。

抛开波湾阴谋时不谣言,笔者强烈建议设想可能性典型用土覆盖的模板指定遗传密码。

另原生的见是,非内联功用模板和内联功用和宏的最重要:终极无叫虫爬着似的感觉。相反,当功用模板建议化的时分,新的正本大都市有上面所说的事功用。鉴于这是原生的天然产生的换异,波湾阴谋器可以在形形色色的的证明切中要害两个完全平稳的的正本,谣言能力或方式由互连器产生的错误。理论地,笔者外出乎这点:这是波湾阴谋器时尚的应关怀。实在上,绝大多数工夫都有规律的运转,笔者不必要处置的养护。。但是,到某种状态巨型使突出,必要创立其的库,上面所说的事成绩会偶然呈现。

首要的,必要提示的是,,在笔者的建议,应用于普通模板功用的方法异样遵从的模板类的会员功用和定态标明会员,和模板会员功用。

发表评论

电子邮件地址不会被公开。 必填项已用*标注