📄 atl under the hood - part 3.mht
字号:
<TR vAlign=3Dtop>
<TD></TD>
<TD></TD></TR>
<TR vAlign=3Dtop>
<TD></TD>
<TD class=3DInfoBarHeader>My Profile</TD></TR>
<TR>
<TD bgColor=3Dblack colSpan=3D2><IMG height=3D1=20
src=3D"http://www.codeproject.com/images/space.gif"=20
width=3D1></TD></TR>
<TR vAlign=3Dtop>
<TD><IMG height=3D16=20
=
src=3D"http://www.codeproject.com/images/profile_small.gif"=20
width=3D16></TD>
<TD class=3DsmallText><A=20
=
href=3D"http://www.codeproject.com/script/profile/modify.asp?ct=3D/atl/at=
l_underthehood_3.asp">My=20
Settings</A></TD></TR>
<TR vAlign=3Dtop>
<TD><IMG height=3D16=20
=
src=3D"http://www.codeproject.com/images/submit_small.gif"=20
width=3D16></TD>
<TD class=3DsmallText><A=20
=
href=3D"http://www.codeproject.com/script/articles/list_articles.asp?user=
id=3D273403">My=20
Articles</A></TD></TR>
<TR vAlign=3Dtop>
<TD><IMG height=3D16=20
=
src=3D"http://www.codeproject.com/images/bookmarks.gif"=20
width=3D16></TD>
<TD class=3DsmallText><A=20
=
href=3D"http://www.codeproject.com/script/profile/bookmark_list.asp">My=20
Bookmarks</A></TD></TR>
<TR vAlign=3Dtop>
<TD><IMG height=3D16=20
=
src=3D"http://www.codeproject.com/images/logoff_small.gif"=20
width=3D16></TD>
<TD class=3DsmallText><A=20
=
href=3D"http://www.codeproject.com/script/profile/logoff.asp?ct=3D/atl/at=
l_underthehood_3.asp">Sign=20
out</A></TD></TR>
<TR>
<TD bgColor=3Dblack colSpan=3D2><IMG height=3D1=20
src=3D"http://www.codeproject.com/images/space.gif"=20
width=3D1></TD></TR></TBODY></TABLE></TD></TR>
<TR>
<TD> </TD></TR>
<TR>
<TD>
<CENTER><A=20
=
href=3D"http://ad.doubleclick.net/jump/N3263.codeproject.com/B1287526;abr=
=3D!ie4;abr=3D!ie5;sz=3D120x600;ord=3D19589425?"><IMG=20
height=3D600 alt=3D"Click Here"=20
=
src=3D"http://ad.doubleclick.net/ad/N3263.codeproject.com/B1287526;abr=3D=
!ie4;abr=3D!ie5;sz=3D120x600;ord=3D19589425?"=20
width=3D120 =
border=3D0></A><BR></CENTER><BR></TD></TR></TBODY></TABLE></TD>
<TD width=3D5 rowSpan=3D2><IMG height=3D1=20
src=3D"http://www.codeproject.com/images/space.gif" width=3D5> =
</TD>
<TD align=3Dright width=3D"100%" bgColor=3Dwhite>
<TABLE width=3D"100%">
<TBODY>
<TR>
<TD class=3DsmallText vAlign=3Dtop noWrap></TD>
<TD noWrap align=3Dright><A name=3D__top></A>
<TABLE>
<TBODY>
<TR>
<TD class=3DsmallText align=3Dright>17 members have =
rated this=20
article. Result:</TD>
<TD>
<TABLE cellSpacing=3D0 cellPadding=3D0 border=3D2>
<TBODY>
<TR>
<TD><IMG height=3D5=20
=
src=3D"http://www.codeproject.com/script/images/red.gif"=20
width=3D20 border=3D0></TD>
<TD><IMG height=3D5=20
=
src=3D"http://www.codeproject.com/script/images/red.gif"=20
width=3D20 border=3D0></TD>
<TD><IMG height=3D5=20
=
src=3D"http://www.codeproject.com/script/images/red.gif"=20
width=3D20 border=3D0></TD>
<TD><IMG height=3D5=20
=
src=3D"http://www.codeproject.com/script/images/red.gif"=20
width=3D20 border=3D0></TD>
<TD><IMG height=3D5=20
=
src=3D"http://www.codeproject.com/script/images/red.gif"=20
width=3D9 border=3D0><IMG height=3D5=20
=
src=3D"http://www.codeproject.com/script/images/white.gif"=20
width=3D11 =
border=3D0></TD></TR></TBODY></TABLE></TD></TR>
<TR>
<TD class=3DsmallText align=3Dright colSpan=3D2><A=20
title=3D"Calculated as rating x Log10(# votes)"=20
=
href=3D"http://www.codeproject.com/script/articles/top_articles.asp?st=3D=
2">Popularity:=20
5.5</A>. Rating: <B>4.47</B> out of=20
5.</TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE></TD></TR>
<TR>
<TD vAlign=3Dtop width=3D"100%">
<DIV id=3Dcontentdiv><!-- Article Starts -->
<H2>Introduction</H2>
<P>One can enjoy the study of ATL if he/she is black belt in =
Templates. In=20
this episode I will try to explain some of the template techniques =
which=20
ATL uses. I don't guarantee that you will become a black belt in =
templates=20
after reading this episode, but I am trying my best that you will =
feel=20
more comfortable with ATL source code after reading this. </P>
<H3>Program 35</H3><PRE><SPAN class=3Dcpp-preprocessor>#include =
<iostream></SPAN>
using <SPAN class=3Dcpp-keyword>namespace</SPAN> std;
<SPAN class=3Dcpp-keyword>template</SPAN> <<SPAN =
class=3Dcpp-keyword>typename</SPAN> T>
T Maximum(<SPAN class=3Dcpp-keyword>const</SPAN> T& a, <SPAN =
class=3Dcpp-keyword>const</SPAN> T& b) {
<SPAN class=3Dcpp-keyword>return</SPAN> a > b ? a : b;
}
<SPAN class=3Dcpp-keyword>int</SPAN> main() {
cout << Maximum(<SPAN class=3Dcpp-literal>5</SPAN>, <SPAN =
class=3Dcpp-literal>10</SPAN>) << endl;
cout << Maximum(<SPAN class=3Dcpp-string>'A'</SPAN>, <SPAN =
class=3Dcpp-string>'B'</SPAN>) << endl;
<SPAN class=3Dcpp-keyword>return</SPAN> <SPAN =
class=3Dcpp-literal>0</SPAN>;
}
</PRE>
<P>The output of this program is</P><PRE lang=3Dtext>10
B</PRE>
<P>Here we don't need to overload the function for int and char =
data type=20
due to template function. Here one thing is important that both =
parameter=20
of the function should have the same data type. But if we want to =
pass=20
different data type then we have to tell the compiler that which =
data type=20
will be considered.</P>
<H3>Program 36</H3><PRE><SPAN class=3Dcpp-preprocessor>#include =
<iostream></SPAN>
using <SPAN class=3Dcpp-keyword>namespace</SPAN> std;
<SPAN class=3Dcpp-keyword>template</SPAN> <<SPAN =
class=3Dcpp-keyword>typename</SPAN> T>
T Maximum(<SPAN class=3Dcpp-keyword>const</SPAN> T& a, <SPAN =
class=3Dcpp-keyword>const</SPAN> T& b) {
<SPAN class=3Dcpp-keyword>return</SPAN> a > b ? a : b;
}
<SPAN class=3Dcpp-keyword>int</SPAN> main() {
cout << Maximum<<SPAN class=3Dcpp-keyword>int</SPAN>>(<SPAN =
class=3Dcpp-literal>5</SPAN>, <SPAN class=3Dcpp-string>'B'</SPAN>) =
<< endl;
cout << Maximum<<SPAN =
class=3Dcpp-keyword>char</SPAN>>(<SPAN class=3Dcpp-literal>5</SPAN>, =
<SPAN class=3Dcpp-string>'B'</SPAN>) << endl;
<SPAN class=3Dcpp-keyword>return</SPAN> <SPAN =
class=3Dcpp-literal>0</SPAN>;
}
</PRE>
<P>The output of this program is</P><PRE lang=3Dtext>66
B</PRE>
<P>We can make the class template too. Here is simplified version =
of=20
template stack class.</P>
<H3>Program 37</H3><PRE><SPAN class=3Dcpp-preprocessor>#include =
<iostream></SPAN>
using <SPAN class=3Dcpp-keyword>namespace</SPAN> std;
<SPAN class=3Dcpp-keyword>template</SPAN> <<SPAN =
class=3Dcpp-keyword>typename</SPAN> T>
<SPAN class=3Dcpp-keyword>class</SPAN> Stack {
<SPAN class=3Dcpp-keyword>private</SPAN>:
T* m_pData;
<SPAN class=3Dcpp-keyword>int</SPAN> m_iTop;
<SPAN class=3Dcpp-keyword>public</SPAN>:
Stack(<SPAN class=3Dcpp-keyword>int</SPAN> p_iSize =3D <SPAN =
class=3Dcpp-literal>0</SPAN>) : m_iTop(<SPAN =
class=3Dcpp-literal>0</SPAN>) {
m_pData =3D <SPAN class=3Dcpp-keyword>new</SPAN> T[p_iSize];
}
<SPAN class=3Dcpp-keyword>void</SPAN> Push(T p_iData) {
m_pData[m_iTop++] =3D p_iData;
}
T Pop() {
<SPAN class=3Dcpp-keyword>return</SPAN> m_pData[--m_iTop];
}
T Top() {
<SPAN class=3Dcpp-keyword>return</SPAN> m_pData[m_iTop];
}
~Stack() {
<SPAN class=3Dcpp-keyword>if</SPAN> (m_pData) {
<SPAN class=3Dcpp-keyword>delete</SPAN> [] m_pData;
}
}
<SPAN class=3Dcpp-keyword>private</SPAN>:
Stack(<SPAN class=3Dcpp-keyword>const</SPAN> Stack<T>&);
Stack<T>& <SPAN class=3Dcpp-keyword>operator</SPAN> =3D =
(<SPAN class=3Dcpp-keyword>const</SPAN> Stack<T>&);
};
<SPAN class=3Dcpp-keyword>int</SPAN> main() {
Stack<<SPAN class=3Dcpp-keyword>int</SPAN>> a(<SPAN =
class=3Dcpp-literal>10</SPAN>);
a.Push(<SPAN class=3Dcpp-literal>10</SPAN>);
a.Push(<SPAN class=3Dcpp-literal>20</SPAN>);
a.Push(<SPAN class=3Dcpp-literal>30</SPAN>);
cout << a.Pop() << endl;
cout << a.Pop() << endl;
cout << a.Pop() << endl;
=09
<SPAN class=3Dcpp-keyword>return</SPAN> <SPAN =
class=3Dcpp-literal>0</SPAN>;
}
</PRE>
<P>There isn't any robust error checking in this program, but the =
purpose=20
of this program is to show the usage of template not making a =
stack class=20
used professionally.</P>
<P>The output of this program is </P><PRE lang=3Dtext>30
20
10</PRE>
<P>We can also pass the data type as a template argument and =
assign a=20
default value to it. Let's change program 36 little bit and pass =
the size=20
of stack as a template parameter rather than constructor =
parameter.</P>
<H3>Program 38</H3><PRE><SPAN class=3Dcpp-preprocessor>#include =
<iostream></SPAN>
using <SPAN class=3Dcpp-keyword>namespace</SPAN> std;
<SPAN class=3Dcpp-keyword>template</SPAN> <<SPAN =
class=3Dcpp-keyword>typename</SPAN> T, <SPAN =
class=3Dcpp-keyword>int</SPAN> iSize =3D <SPAN =
class=3Dcpp-literal>10</SPAN>>
<SPAN class=3Dcpp-keyword>class</SPAN> Stack {
<SPAN class=3Dcpp-keyword>private</SPAN>:
T m_pData[iSize];
<SPAN class=3Dcpp-keyword>int</SPAN> m_iTop;
<SPAN class=3Dcpp-keyword>public</SPAN>:
Stack() : m_iTop(<SPAN class=3Dcpp-literal>0</SPAN>) {
}
<SPAN class=3Dcpp-keyword>void</SPAN> Push(T p_iData) {
m_pData[m_iTop++] =3D p_iData;
}
T Pop() {
<SPAN class=3Dcpp-keyword>return</SPAN> m_pData[--m_iTop];
}
T Top() {
<SPAN class=3Dcpp-keyword>return</SPAN> m_pData[m_iTop];
}
<SPAN class=3Dcpp-keyword>private</SPAN>:
Stack(<SPAN class=3Dcpp-keyword>const</SPAN> Stack<T>&);
Stack<T>& <SPAN class=3Dcpp-keyword>operator</SPAN> =3D =
(<SPAN class=3Dcpp-keyword>const</SPAN> Stack<T>&);
};
<SPAN class=3Dcpp-keyword>int</SPAN> main() {
Stack<<SPAN class=3Dcpp-keyword>int</SPAN>, <SPAN =
class=3Dcpp-literal>10</SPAN>> a;
a.Push(<SPAN class=3Dcpp-literal>10</SPAN>);
a.Push(<SPAN class=3Dcpp-literal>20</SPAN>);
a.Push(<SPAN class=3Dcpp-literal>30</SPAN>);
cout << a.Pop() << endl;
cout << a.Pop() << endl;
cout << a.Pop() << endl;
=09
<SPAN class=3Dcpp-keyword>return</SPAN> <SPAN =
class=3Dcpp-literal>0</SPAN>;
}
</PRE>
<P>The output of this program is same as pervious program. The =
important=20
part of this program is.</P><PRE><SPAN =
class=3Dcpp-keyword>template</SPAN> <<SPAN =
class=3Dcpp-keyword>typename</SPAN> T, <SPAN =
class=3Dcpp-keyword>int</SPAN> iSize =3D <SPAN =
class=3Dcpp-literal>10</SPAN>></PRE>
<P>Now there is a question which approach is better? Passing =
template=20
parameter is always faster then passing parameter by constructor. =
Why?=20
Because when you pass stack size in template parameter then the =
array of=20
given data type is created automatic (i.e. created on stack), =
however=20
passing parameter by constructor means constructor has to allocate =
memory=20
during run time by new or malloc family of functions. If we are =
sure that=20
we are not going to change the size of stack once we made this, as =
we have=20
done in above program by making copy constructor and assignment =
operator=20
private, then use template parameter is better approach.</P>
<P>You can also pass user define class as a parameter in place of =
type=20
parameter, but be sure that class have all the overloaded =
operators which=20
is used in that template function or template class. </P>
<P>E.g. take a look at Maximum function of program 35. This =
program use=20
one operator >, so if we pass our own class then that class =
must have=20
overloaded > operator. Here is a program which shows this. </P>
<H3>Program 39</H3><PRE><SPAN class=3Dcpp-preprocessor>#include =
<iostream></SPAN>
using <SPAN class=3Dcpp-keyword>namespace</SPAN> std;
<SPAN class=3Dcpp-keyword>template</SPAN> <<SPAN =
class=3Dcpp-keyword>typename</SPAN> T>
T Maximum(<SPAN class=3Dcpp-keyword>const</SPAN> T& a, <SPAN =
class=3Dcpp-keyword>const</SPAN> T& b) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -