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

📄 atl under the hood - part 1.mht

📁 大家知道wtl是window UI库
💻 MHT
📖 第 1 页 / 共 5 页
字号:
	<SPAN class=3Dcpp-keyword>return</SPAN> <SPAN =
class=3Dcpp-literal>0</SPAN>;
}
</PRE>
      <P>The output of this program is </P><PRE>Base1::f
Base1::g
Base2::f
Base2::f
Base3::f
Base3::f
Drive::fd
Drive::gd
</PRE>
      <P>This program show that the virtual function of drive store in =
the=20
      vtable of first vptr.=20
      <P>
      <CENTER><IMG height=3D277=20
      src=3D"http://www.codeproject.com/atl/ATL_UnderTheHood_/CPP6.GIF"=20
      width=3D400></CENTER><BR>We can get the offset of Drive class vptr =
with the=20
      help of <CODE><SPAN class=3Dcpp-keyword>static_cast</SPAN></CODE>. =
Let's=20
      take a look at he following program to better understand it.
      <P></P>
      <H3>Program 16.</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>:
	<SPAN class=3Dcpp-keyword>virtual</SPAN> <SPAN =
class=3Dcpp-keyword>void</SPAN> f() { }
};

<SPAN class=3Dcpp-keyword>class</SPAN> Base2 {
<SPAN class=3Dcpp-keyword>public</SPAN>:
	<SPAN class=3Dcpp-keyword>virtual</SPAN> <SPAN =
class=3Dcpp-keyword>void</SPAN> f() { }
};

<SPAN class=3Dcpp-keyword>class</SPAN> Base3 {
<SPAN class=3Dcpp-keyword>public</SPAN>:
	<SPAN class=3Dcpp-keyword>virtual</SPAN> <SPAN =
class=3Dcpp-keyword>void</SPAN> f() { }
};

<SPAN class=3Dcpp-keyword>class</SPAN> Drive : <SPAN =
class=3Dcpp-keyword>public</SPAN> Base1, <SPAN =
class=3Dcpp-keyword>public</SPAN> Base2, <SPAN =
class=3Dcpp-keyword>public</SPAN> Base3 {
};

<SPAN class=3Dcpp-comment>// any non zero value because multiply zero =
with any no is zero</SPAN>
<SPAN class=3Dcpp-preprocessor>#define SOME_VALUE	1</SPAN>

<SPAN class=3Dcpp-keyword>int</SPAN> main() {
	cout &lt;&lt; (DWORD)<SPAN =
class=3Dcpp-keyword>static_cast</SPAN>&lt;Base1*&gt;((Drive*)SOME_VALUE)-=
SOME_VALUE &lt;&lt; endl;
	cout &lt;&lt; (DWORD)<SPAN =
class=3Dcpp-keyword>static_cast</SPAN>&lt;Base2*&gt;((Drive*)SOME_VALUE)-=
SOME_VALUE &lt;&lt; endl;
	cout &lt;&lt; (DWORD)<SPAN =
class=3Dcpp-keyword>static_cast</SPAN>&lt;Base3*&gt;((Drive*)SOME_VALUE)-=
SOME_VALUE &lt;&lt; endl;
	<SPAN class=3Dcpp-keyword>return</SPAN> <SPAN =
class=3Dcpp-literal>0</SPAN>;
}
</PRE>
      <P>ATL use a macro name offsetofclass defined in ATLDEF.H to do =
this.=20
      Macro is defined at </P><PRE><SPAN =
class=3Dcpp-preprocessor>#define offsetofclass(base, derived) \</SPAN>
       ((DWORD)(<SPAN =
class=3Dcpp-keyword>static_cast</SPAN>&lt;base*&gt;((derived*)_ATL_PACKIN=
G))-_ATL_PACKING)
</PRE>
      <P>This macro returns the offset of the base class vptr in the =
drive class=20
      object model. Let's see an example to get an idea of this=20
      <H3>Program 17.</H3><PRE><SPAN class=3Dcpp-preprocessor>#include =
&lt;windows.h&gt;</SPAN>
<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>:
	<SPAN class=3Dcpp-keyword>virtual</SPAN> <SPAN =
class=3Dcpp-keyword>void</SPAN> f() { }
};

<SPAN class=3Dcpp-keyword>class</SPAN> Base2 {
<SPAN class=3Dcpp-keyword>public</SPAN>:
	<SPAN class=3Dcpp-keyword>virtual</SPAN> <SPAN =
class=3Dcpp-keyword>void</SPAN> f() { }
};

<SPAN class=3Dcpp-keyword>class</SPAN> Base3 {
<SPAN class=3Dcpp-keyword>public</SPAN>:
	<SPAN class=3Dcpp-keyword>virtual</SPAN> <SPAN =
class=3Dcpp-keyword>void</SPAN> f() { }
};

<SPAN class=3Dcpp-keyword>class</SPAN> Drive : <SPAN =
class=3Dcpp-keyword>public</SPAN> Base1, <SPAN =
class=3Dcpp-keyword>public</SPAN> Base2, <SPAN =
class=3Dcpp-keyword>public</SPAN> Base3 {
};

<SPAN class=3Dcpp-preprocessor>#define _ATL_PACKING 8</SPAN>

<SPAN class=3Dcpp-preprocessor>#define offsetofclass(base, derived) =
\</SPAN>
	((DWORD)(<SPAN =
class=3Dcpp-keyword>static_cast</SPAN>&lt;base*&gt;((derived*)_ATL_PACKIN=
G))-_ATL_PACKING)

<SPAN class=3Dcpp-keyword>int</SPAN> main() {
	cout &lt;&lt; offsetofclass(Base1, Drive) &lt;&lt; endl;
	cout &lt;&lt; offsetofclass(Base2, Drive) &lt;&lt; endl;
	cout &lt;&lt; offsetofclass(Base3, Drive) &lt;&lt; endl;
	<SPAN class=3Dcpp-keyword>return</SPAN> <SPAN =
class=3Dcpp-literal>0</SPAN>;
}
</PRE>
      <P>The memory layout of the drive class is=20
      <CENTER><IMG height=3D145=20
      src=3D"http://www.codeproject.com/atl/ATL_UnderTheHood_/CPP5.GIF"=20
      width=3D241></CENTER><BR>And output of this program is <PRE><SPAN =
class=3Dcpp-literal>0</SPAN>
<SPAN class=3Dcpp-literal>4</SPAN>
<SPAN class=3Dcpp-literal>8</SPAN>
</PRE>
      <P>Output of this program shows this macro returns the offset of =
vptr of=20
      the required base class. In Don Box's Essential COM, he used a =
similar=20
      macro to this. Change the program little bit and replace ATL macro =
with=20
      Box's macro.=20
      <H3>Program 18.</H3><PRE><SPAN class=3Dcpp-preprocessor>#include =
&lt;windows.h&gt;</SPAN>
<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>:
	<SPAN class=3Dcpp-keyword>virtual</SPAN> <SPAN =
class=3Dcpp-keyword>void</SPAN> f() { }
};

<SPAN class=3Dcpp-keyword>class</SPAN> Base2 {
<SPAN class=3Dcpp-keyword>public</SPAN>:
	<SPAN class=3Dcpp-keyword>virtual</SPAN> <SPAN =
class=3Dcpp-keyword>void</SPAN> f() { }
};

<SPAN class=3Dcpp-keyword>class</SPAN> Base3 {
<SPAN class=3Dcpp-keyword>public</SPAN>:
	<SPAN class=3Dcpp-keyword>virtual</SPAN> <SPAN =
class=3Dcpp-keyword>void</SPAN> f() { }
};

<SPAN class=3Dcpp-keyword>class</SPAN> Drive : <SPAN =
class=3Dcpp-keyword>public</SPAN> Base1, <SPAN =
class=3Dcpp-keyword>public</SPAN> Base2, <SPAN =
class=3Dcpp-keyword>public</SPAN> Base3 {
};

<SPAN class=3Dcpp-preprocessor>#define BASE_OFFSET(ClassName, BaseName) =
\</SPAN>
	(DWORD(<SPAN =
class=3Dcpp-keyword>static_cast</SPAN>&lt;BaseName*&gt;(<SPAN =
class=3Dcpp-keyword>reinterpret_cast</SPAN>&lt;ClassName*&gt;\
	(<SPAN class=3Dcpp-literal>0x10000000</SPAN>))) - <SPAN =
class=3Dcpp-literal>0x10000000</SPAN>)

<SPAN class=3Dcpp-keyword>int</SPAN> main() {
	cout &lt;&lt; BASE_OFFSET(Drive, Base1) &lt;&lt; endl;
	cout &lt;&lt; BASE_OFFSET(Drive, Base2) &lt;&lt; endl;
	cout &lt;&lt; BASE_OFFSET(Drive, Base3) &lt;&lt; endl;
	<SPAN class=3Dcpp-keyword>return</SPAN> <SPAN =
class=3Dcpp-literal>0</SPAN>;
}
</PRE>
      <P>The output and purpose of this program is the same as the =
previous=20
      program.=20
      <P>Let's do something practical and use this macro in our program. =
In fact=20
      we can call the virtual function of our required base class by =
getting the=20
      offset of base class vptr in drive's memory structure.</P>
      <H3>Program 19.</H3><PRE><SPAN class=3Dcpp-preprocessor>#include =
&lt;windows.h&gt;</SPAN>
<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>:
	<SPAN class=3Dcpp-keyword>virtual</SPAN> <SPAN =
class=3Dcpp-keyword>void</SPAN> f() { cout &lt;&lt; "Base1::f()" =
&lt;&lt; endl; }
};

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

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

<SPAN class=3Dcpp-keyword>class</SPAN> Drive : <SPAN =
class=3Dcpp-keyword>public</SPAN> Base1, <SPAN =
class=3Dcpp-keyword>public</SPAN> Base2, <SPAN =
class=3Dcpp-keyword>public</SPAN> Base3 {
};

<SPAN class=3Dcpp-preprocessor>#define _ATL_PACKING 8</SPAN>

<SPAN class=3Dcpp-preprocessor>#define offsetofclass(base, derived) =
\</SPAN>
	((DWORD)(<SPAN =
class=3Dcpp-keyword>static_cast</SPAN>&lt;base*&gt;((derived*)_ATL_PACKIN=
G))-_ATL_PACKING)

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

	<SPAN class=3Dcpp-keyword>void</SPAN>* pVoid =3D NULL;

	<SPAN class=3Dcpp-comment>// call function of Base1</SPAN>
	pVoid =3D (<SPAN class=3Dcpp-keyword>char</SPAN>*)&amp;d + =
offsetofclass(Base1, Drive);
	((Base1*)(pVoid))-&gt;f();

	<SPAN class=3Dcpp-comment>// call function of Base2</SPAN>
	pVoid =3D (<SPAN class=3Dcpp-keyword>char</SPAN>*)&amp;d + =
offsetofclass(Base2, Drive);
	((Base2*)(pVoid))-&gt;f();

	<SPAN class=3Dcpp-comment>// call function of Base1</SPAN>
	pVoid =3D (<SPAN class=3Dcpp-keyword>char</SPAN>*)&amp;d + =
offsetofclass(Base3, Drive);
	((Base3*)(pVoid))-&gt;f();

	<SPAN class=3Dcpp-keyword>return</SPAN> <SPAN =
class=3Dcpp-literal>0</SPAN>;
}
</PRE>
      <P>The output of the program is </P><PRE>Base1::f()
Base2::f()
Base3::f()
</PRE>
      <P>I tried to explain the working of <CODE>offsetofclass</CODE> =
macro of=20
      ATL in this tutorial. I Hope to explore other mysterious of ATL in =
the=20
      next article. <!-- Article Ends --></P></DIV>
      <H2>About Zeeshan Amjad</H2>
      <TABLE width=3D"100%" border=3D0>
        <TBODY>
        <TR vAlign=3Dtop>
          <TD class=3DsmallText noWrap><BR></TD>
          <TD class=3DsmallText width=3D"100%">Software Engineer at =
SoftPak=20
            Financial Systems<BR><A=20
            =
href=3D"http://www.softpak.com/">http://www.softpak.com/</A><BR><BR>And=20
            sometimes teaching Object Oriented programming and C++ in =
University=20
            of Karachi as a Visiting Faculty Member.<BR><A=20
            href=3D"http://www.csku.edu.pk/">http://www.csku.edu.pk/</A>
            <P class=3DsmallText>Click <A=20
            =
href=3D"http://www.codeproject.com/script/profile/whos_who.asp?vt=3Darts&=
amp;id=3D5890">here</A>=20
            to view Zeeshan Amjad's online =
profile.</P></TD></TR></TBODY></TABLE><BR>
      <H2>Other popular ATL articles:</H2>
      <UL>
        <LI><A=20
        =
href=3D"http://www.codeproject.com/atl/shellfoldertree.asp">ShellFolderTr=
ee</A><BR><SPAN=20
        class=3Dsmalltext>Mimicking and extending the shell=92s =
folder-tree control=20
        functionality</SPAN>
        <LI><A href=3D"http://www.codeproject.com/atl/atlserver.asp">ATL =
Server -=20
        Web Application/Web Service</A><BR><SPAN class=3Dsmalltext>Web=20
        Application/Web Service development using ATL Server =
classes</SPAN>
        <LI><A =
href=3D"http://www.codeproject.com/atl/newinatl7.asp">What's new in=20
        ATL7</A><BR><SPAN class=3Dsmalltext>Overview of new classes in =
ATL7</SPAN>
        <LI><A=20
        =
href=3D"http://www.codeproject.com/atl/ietoolbartutorial.asp">Internet=20
        Explorer Toolbar (Deskband) Tutorial</A><BR><SPAN =
class=3Dsmalltext>A=20
        tutorial on Using RBDeskband and CWindowImpl ATL Object Wizards =
to=20
        create an Internet Explorer(IE) Toolbar.</SPAN></LI></UL>
      <FORM action=3D/script/rating/code/app/insert_vote.asp =
method=3Dpost><INPUT=20
      type=3Dhidden value=3D/atl/ATL_UnderTheHood_.asp-1/28/2002 =
name=3Dvote_name>=20
      <INPUT type=3Dhidden value=3D/atl/atl_underthehood_.asp =
name=3Dgoal>=20
      <TABLE cellSpacing=3D0 cellPadding=3D1 width=3D"100%" =
bgColor=3D#ff9900=20
        border=3D0><TBODY>
        <TR>
          <TD width=3D"100%">
            <TABLE cellSpacing=3D0 cellPadding=3D4 width=3D"100%" =
bgColor=3D#fbedbb=20
            border=3D0>
              <TBODY>
              <TR>
         

⌨️ 快捷键说明

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