⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 atl under the hood - part 3.mht

📁 大家知道wtl是window UI库
💻 MHT
📖 第 1 页 / 共 5 页
字号:

	obj1.Play();
	obj2.Play();

	<SPAN class=3Dcpp-keyword>return</SPAN> <SPAN =
class=3Dcpp-literal>0</SPAN>;
}
</PRE>
      <P>Here Round1 and Round2 are classes of different round of a game =
and=20
      Strategy class decide what do to do depend on the template =
parameter pass=20
      to this class.</P>
      <P>The output of the program is</P><PRE lang=3Dtext>Round1::Play
Round2::Play</PRE>
      <P>ATL implement threading using Strategy design pattern.</P>
      <P>Proxy design pattern can also be implemented using template. =
Smart=20
      pointer is an example of proxy design pattern. Here is an example =
of=20
      simplified version of smart pointer without using template.</P>
      <H3>Program 46</H3><PRE><SPAN class=3Dcpp-preprocessor>#include =
&lt;iostream&gt;</SPAN>
using <SPAN class=3Dcpp-keyword>namespace</SPAN> std;

<SPAN class=3Dcpp-keyword>class</SPAN> Inner {
<SPAN class=3Dcpp-keyword>public</SPAN>:
	<SPAN class=3Dcpp-keyword>void</SPAN> Fun() {
		cout &lt;&lt; "Inner::Fun" &lt;&lt; endl;
	}
};

<SPAN class=3Dcpp-keyword>class</SPAN> Outer {
<SPAN class=3Dcpp-keyword>private</SPAN>:
	Inner* m_pInner;

<SPAN class=3Dcpp-keyword>public</SPAN>:
	Outer(Inner* p_pInner) : m_pInner(p_pInner) {
	}

	Inner* <SPAN class=3Dcpp-keyword>operator</SPAN> -&gt; () {
		<SPAN class=3Dcpp-keyword>return</SPAN> m_pInner;
	}
};

<SPAN class=3Dcpp-keyword>int</SPAN> main() {
	Inner objInner;
	Outer objOuter(&amp;objInner);

	objOuter-&gt;Fun();

	<SPAN class=3Dcpp-keyword>return</SPAN> <SPAN =
class=3Dcpp-literal>0</SPAN>;
}
</PRE>
      <P>The output of the program is</P><PRE =
lang=3Dtext>Inner::Fun()</PRE>
      <P>For simplicity, we just overload the -&gt; operator, but in =
real smart=20
      pointer all the necessary operators such as =3D, =3D=3D, !, &amp;, =
* are=20
      overloaded. There is one big problem with this smart pointer; this =
can=20
      only contain pointer to Inner object. We can remove this =
restriction by=20
      making OuterClass template. Let's change program little bit.</P>
      <H3>Program 47</H3><PRE><SPAN class=3Dcpp-preprocessor>#include =
&lt;iostream&gt;</SPAN>
using <SPAN class=3Dcpp-keyword>namespace</SPAN> std;

<SPAN class=3Dcpp-keyword>class</SPAN> Inner {
<SPAN class=3Dcpp-keyword>public</SPAN>:
	<SPAN class=3Dcpp-keyword>void</SPAN> Fun() {
		cout &lt;&lt; "Inner::Fun" &lt;&lt; endl;
	}
};

<SPAN class=3Dcpp-keyword>template</SPAN> &lt;<SPAN =
class=3Dcpp-keyword>typename</SPAN> T&gt;
<SPAN class=3Dcpp-keyword>class</SPAN> Outer {
<SPAN class=3Dcpp-keyword>private</SPAN>:
	T* m_pInner;

<SPAN class=3Dcpp-keyword>public</SPAN>:
	Outer(T* p_pInner) : m_pInner(p_pInner) {
	}

	T* <SPAN class=3Dcpp-keyword>operator</SPAN> -&gt; () {
		<SPAN class=3Dcpp-keyword>return</SPAN> m_pInner;
	}
};

<SPAN class=3Dcpp-keyword>int</SPAN> main() {
	Inner objInner;
	Outer&lt;Inner&gt; objOuter(&amp;objInner);

	objOuter-&gt;Fun();

	<SPAN class=3Dcpp-keyword>return</SPAN> <SPAN =
class=3Dcpp-literal>0</SPAN>;
}
</PRE>
      <P>The output of the program is same as previous one but now =
OuterClass=20
      can contain any class whose type is passed as a template =
parameter.</P>
      <P>ATL has two smart pointer classes. <CODE>CComPtr</CODE> and=20
      <CODE>CComQIPtr</CODE>.</P>
      <P>You can do some interesting work with the help of template. =
E.g. your=20
      class can be child of different base class depend on different=20
      situation.</P>
      <H3>Program 48</H3><PRE><SPAN class=3Dcpp-preprocessor>#include =
&lt;iostream&gt;</SPAN>
using <SPAN class=3Dcpp-keyword>namespace</SPAN> std;

<SPAN class=3Dcpp-keyword>class</SPAN> Base1 {
<SPAN class=3Dcpp-keyword>public</SPAN>:
	Base1() {
		cout &lt;&lt; "Base1::Base1" &lt;&lt; endl;
	}
};

<SPAN class=3Dcpp-keyword>class</SPAN> Base2 {
<SPAN class=3Dcpp-keyword>public</SPAN>:
	Base2() {
		cout &lt;&lt; "Base2::Base2" &lt;&lt; endl;
	}
};

<SPAN class=3Dcpp-keyword>template</SPAN> &lt;<SPAN =
class=3Dcpp-keyword>typename</SPAN> T&gt;
<SPAN class=3Dcpp-keyword>class</SPAN> Drive : <SPAN =
class=3Dcpp-keyword>public</SPAN> T {
<SPAN class=3Dcpp-keyword>public</SPAN>:
	Drive() {
		cout &lt;&lt; "Drive::Drive" &lt;&lt; endl;
	}
};

<SPAN class=3Dcpp-keyword>int</SPAN> main() {

	Drive&lt;Base1&gt; obj1;
	Drive&lt;Base2&gt; obj2;
	<SPAN class=3Dcpp-keyword>return</SPAN> <SPAN =
class=3Dcpp-literal>0</SPAN>;
}
</PRE>
      <P>The output of this program is</P><PRE lang=3Dtext>Base1::Base1
Drive::Drive
Base2::Base2
Drive::Drive
</PRE>
      <P>Here the Drive class is inherited from Base1 and Base2 depend =
on the=20
      parameter passed to the template at the time of creation of =
object.</P>
      <P>ATL use this technique. When you make a COM component using ATL =
then=20
      <CODE>CComObject</CODE> is inherit from your class. Here ATL take=20
      advantage of template, because ATL doesn't know in advance the =
name of the=20
      class which you create to make COM component. CComObject class is =
define=20
      in ATLCOM.h file</P>
      <P>We can simulate virtual functions too with the help of =
template. Let's=20
      recall virtual function once again. Here is a simple program to =
recall the=20
      virtual function.</P>
      <H3>Program 49</H3><PRE><SPAN class=3Dcpp-preprocessor>#include =
&lt;iostream&gt;</SPAN>
using <SPAN class=3Dcpp-keyword>namespace</SPAN> std;

<SPAN class=3Dcpp-keyword>class</SPAN> Base {
<SPAN class=3Dcpp-keyword>public</SPAN>:
	<SPAN class=3Dcpp-keyword>virtual</SPAN> <SPAN =
class=3Dcpp-keyword>void</SPAN> fun() {
		cout &lt;&lt; "Base::fun" &lt;&lt; endl;
	}

	<SPAN class=3Dcpp-keyword>void</SPAN> doSomething() {
		fun();
	}
};

<SPAN class=3Dcpp-keyword>class</SPAN> Drive : <SPAN =
class=3Dcpp-keyword>public</SPAN> Base {
<SPAN class=3Dcpp-keyword>public</SPAN>:
	<SPAN class=3Dcpp-keyword>void</SPAN> fun() {
		cout &lt;&lt; "Drive::fun" &lt;&lt; endl;
	}
};

<SPAN class=3Dcpp-keyword>int</SPAN> main() {
	Drive obj;
	obj.doSomething();

	<SPAN class=3Dcpp-keyword>return</SPAN> <SPAN =
class=3Dcpp-literal>0</SPAN>;
}
</PRE>
      <P>The output of the program is </P><PRE lang=3Dtext>Drive::fun
</PRE>
      <P>We can get the same behavior with the help of template.</P>
      <H3>Program 50</H3><PRE><SPAN class=3Dcpp-preprocessor>#include =
&lt;iostream&gt;</SPAN>
using <SPAN class=3Dcpp-keyword>namespace</SPAN> std;

<SPAN class=3Dcpp-keyword>template</SPAN> &lt;<SPAN =
class=3Dcpp-keyword>typename</SPAN> T&gt;
<SPAN class=3Dcpp-keyword>class</SPAN> Base {
<SPAN class=3Dcpp-keyword>public</SPAN>:
	<SPAN class=3Dcpp-keyword>void</SPAN> fun() {
		cout &lt;&lt; "Base::fun" &lt;&lt; endl;
	}

	<SPAN class=3Dcpp-keyword>void</SPAN> doSomething() {
		T* pT =3D <SPAN class=3Dcpp-keyword>static_cast</SPAN>&lt;T*&gt;(<SPAN =
class=3Dcpp-keyword>this</SPAN>);
		pT-&gt;fun();
	}
};

<SPAN class=3Dcpp-keyword>class</SPAN> Drive : <SPAN =
class=3Dcpp-keyword>public</SPAN> Base&lt;Drive&gt; {
<SPAN class=3Dcpp-keyword>public</SPAN>:
	<SPAN class=3Dcpp-keyword>void</SPAN> fun() {
		cout &lt;&lt; "Drive::fun" &lt;&lt; endl;
	}
};

<SPAN class=3Dcpp-keyword>int</SPAN> main() {
	Drive obj;
	obj.doSomething();

	<SPAN class=3Dcpp-keyword>return</SPAN> <SPAN =
class=3Dcpp-literal>0</SPAN>;
}
</PRE>
      <P>The output of the program is same as previous one. So we can =
simulate=20
      the behavior of virtual function with the help of template.</P>
      <P>The interesting parts of this program are</P><PRE><SPAN =
class=3Dcpp-keyword>class</SPAN> Drive : <SPAN =
class=3Dcpp-keyword>public</SPAN> Base&lt;Drive&gt; {
</PRE>
      <P>This shows that we can pass the Drive class as a template =
parameter.=20
      The other interesting part of the program is the =
<CODE>doSomething</CODE>=20
      function of base class.</P><PRE>T* pT =3D <SPAN =
class=3Dcpp-keyword>static_cast</SPAN>&lt;T*&gt;(<SPAN =
class=3Dcpp-keyword>this</SPAN>);
pT-&gt;fun();</PRE>
      <P>Here the base class pointer is converted into drive class =
pointer,=20
      because drive class is passed as a template parameter of Base =
class. Then=20
      function is executed from that pointer, Now that pointer points to =
drive=20
      class object, so the drive class object is called.</P>
      <P>But there is very good question, why should we do this? And =
there is=20
      very good answer of this question so save the extra byes of =
virtual=20
      pointer, virtual table and save the extra time to call virtual =
function.=20
      This is the main philosophy of ATL to make component as small as =
possible=20
      and as fast as possible.</P>
      <P>Now there is one more question may arise in the mind. If due to =
this=20
      technique you can simulate virtual function with less memory and =
faster=20
      then original virtual function then why should we call virtual =
function?=20
      Shouldn't we replace all virtual function with this technique? The =
short=20
      answer of this question is no, we can not replace all virtual =
function=20
      with this technique. </P>
      <P>There are some problems with this technique. First you can not =
further=20
      inherit any class from <CODE>Drive</CODE> class. If you try to do =
so then=20
      that function will no more act as a virtual function. It doesn't =
happen in=20
      the case of virtual function; once you declare function virtual =
then it=20
      becomes virtual in all of drive class no matter how deep in =
inheritance=20
      chain. Let's take a look at a program what happen when we inherit =
one more=20
      class from Drive.</P>
      <H3>Program 51</H3><PRE><SPAN class=3Dcpp-preprocessor>#include =
&lt;iostream&gt;</SPAN>
using <SPAN class=3Dcpp-keyword>namespace</SPAN> std;

<SPAN class=3Dcpp-keyword>template</SPAN> &lt;<SPAN =
class=3Dcpp-keyword>typename</SPAN> T&gt;
<SPAN class=3Dcpp-keyword>class</SPAN> Base {
<SPAN class=3Dcpp-keyword>public</SPAN>:
	<SPAN class=3Dcpp-keyword>void</SPAN> fun() {
		cout &lt;&lt; "Base::fun" &lt;&lt; endl;
	}

	<SPAN class=3Dcpp-keyword>void</SPAN> doSomething() {
		T* pT =3D <SPAN class=3Dcpp-keyword>static_cast</SPAN>&lt;T*&gt;(<SPAN =
class=3Dcpp-keyword>this</SPAN>);
		pT-&gt;fun();
	}
};

<SPAN class=3Dcpp-keyword>class</SPAN> Drive : <SPAN =
class=3Dcpp-keyword>public</SPAN> Base&lt;Drive&gt; {
<SPAN class=3Dcpp-keyword>public</SPAN>:
	<SPAN class=3Dcpp-keyword>void</SPAN> fun() {
		cout &lt;&lt; "Drive::fun" &lt;&lt; endl;
	}
};

<SPAN class=3Dcpp-keyword>class</SPAN> MostDrive : <SPAN =
class=3Dcpp-keyword>public</SPAN> Drive {
<SPAN class=3Dcpp-keyword>public</SPAN>:
	<SPAN class=3Dcpp-keyword>void</SPAN> fun() {
		cout &lt;&lt; "MostDrive::fun" &lt;&lt; endl;
	}
};

<SPAN class=3Dcpp-keyword>int</SPAN> main() {
	MostDrive obj;
	obj.doSomething();

	<SPAN class=3Dcpp-keyword>return</SPAN> <SPAN =
class=3Dcpp-literal>0</SPAN>;
}
</PRE>
      <P>The output of this is program as same as previous one. In case =
of=20
      virtual function the output should be</P><PRE>MostDrive::fun</PRE>
      <P>There is one more problem with this technique, when we want to =
take=20
      pointer of <CODE>Base</CODE> class and want to store address of =
drive=20
      class.</P>
      <H3>Program 52</H3><PRE><SPAN class=3Dcpp-preprocessor>#include =
&lt;iostream&gt;</SPAN>
using <SPAN class=3Dcpp-keyword>namespace</SPAN> std;

<SPAN class=3Dcpp-keyword>template</SPAN> &lt;<SPAN =
class=3Dcpp-keyword>typename</SPAN> T&gt;
<SPAN class=3Dcpp-keyword>class</SPAN> Base {
<SPAN class=3Dcpp-keyword>public</SPAN>:
	<SPAN class=3Dcpp-keyword>void</SPAN> fun() {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -