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

📄 atl under the hood - part 2.mht

📁 大家知道wtl是window UI库
💻 MHT
📖 第 1 页 / 共 5 页
字号:
      =
src=3D"http://www.codeproject.com/atl/ATL_UnderTheHood_2/ATL_2_PIC_1.JPG"=
=20
      width=3D276></CENTER>
      <P>And when you press Ignore button then it display one more =
dialog=20
      <P>
      <CENTER><IMG height=3D210=20
      =
src=3D"http://www.codeproject.com/atl/ATL_UnderTheHood_2/ATL_2_PIC_2.JPG"=
=20
      width=3D276></CENTER>And in release mode it just displays the =
error message=20
      in the output console window. <PRE>In Base
Virtual Pointer =3D 0012FF80
Address of Vtable =3D 0042115C
Value at Vtable 1st entry =3D 0041245D
Value at Vtable 2nd entry =3D 0041245D

runtime error R6025
- pure <SPAN class=3Dcpp-keyword>virtual</SPAN> function call
</PRE>Here what is R6025? It is defined in CMSGS.H file which define all =

      error messages used within the C run time library. <PRE><SPAN =
class=3Dcpp-preprocessor>#define _RT_PUREVIRT_TXT   "R6025" EOL "- pure =
virtual function call" EOL</SPAN>
</PRE>In fact when we define pure virtual function then compiler place =
the=20
      address of one of the C Runtime library function =
<CODE>_purecall</CODE>.=20
      This function is define in PUREVIRT.C and have the following =
prototype. <PRE><SPAN class=3Dcpp-keyword>void</SPAN> __cdecl =
_purecall(<SPAN class=3Dcpp-keyword>void</SPAN>)
</PRE>We can achieve the same behavior by directly calling this function =

      from our program. Let's take a look at this very small program.=20
      <H3>Program 29</H3><PRE><SPAN class=3Dcpp-keyword>int</SPAN> =
main() {
    _purecall();   =20
    <SPAN class=3Dcpp-keyword>return</SPAN> <SPAN =
class=3Dcpp-literal>0</SPAN>;
}
</PRE>The out put of this program is same as previous one in both debug=20
      and release mode. To better understand this make the inheritance =
chain=20
      deeper and drive one more class from Drive and see the behavior of =
this.=20
      <H3>Program 30</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>:
    Base() {
        cout &lt;&lt; <SPAN class=3Dcpp-string>"In Base"</SPAN> &lt;&lt; =
endl;
        cout &lt;&lt; <SPAN class=3Dcpp-string>"Virtual Pointer =3D =
"</SPAN> &lt;&lt; (<SPAN class=3Dcpp-keyword>int</SPAN>*)<SPAN =
class=3Dcpp-keyword>this</SPAN> &lt;&lt; endl;
        cout &lt;&lt; <SPAN class=3Dcpp-string>"Address of Vtable =3D =
"</SPAN> &lt;&lt; (<SPAN class=3Dcpp-keyword>int</SPAN>*)*(<SPAN =
class=3Dcpp-keyword>int</SPAN>*)<SPAN class=3Dcpp-keyword>this</SPAN> =
&lt;&lt; endl;
        cout &lt;&lt; <SPAN class=3Dcpp-string>"Value at Vtable 1st =
entry =3D "</SPAN> &lt;&lt; (<SPAN =
class=3Dcpp-keyword>int</SPAN>*)*((<SPAN =
class=3Dcpp-keyword>int</SPAN>*)*(<SPAN =
class=3Dcpp-keyword>int</SPAN>*)<SPAN =
class=3Dcpp-keyword>this</SPAN>+<SPAN class=3Dcpp-literal>0</SPAN>) =
&lt;&lt; endl;
        cout &lt;&lt; <SPAN class=3Dcpp-string>"Value at Vtable 2nd =
entry =3D "</SPAN> &lt;&lt; (<SPAN =
class=3Dcpp-keyword>int</SPAN>*)*((<SPAN =
class=3Dcpp-keyword>int</SPAN>*)*(<SPAN =
class=3Dcpp-keyword>int</SPAN>*)<SPAN =
class=3Dcpp-keyword>this</SPAN>+<SPAN class=3Dcpp-literal>1</SPAN>) =
&lt;&lt; endl;
        cout &lt;&lt; endl;
    }
    <SPAN class=3Dcpp-keyword>virtual</SPAN> <SPAN =
class=3Dcpp-keyword>void</SPAN> f1() =3D <SPAN =
class=3Dcpp-literal>0</SPAN>;
    <SPAN class=3Dcpp-keyword>virtual</SPAN> <SPAN =
class=3Dcpp-keyword>void</SPAN> f2() =3D <SPAN =
class=3Dcpp-literal>0</SPAN>;
};

<SPAN class=3Dcpp-keyword>class</SPAN> Drive : <SPAN =
class=3Dcpp-keyword>public</SPAN> Base {
<SPAN class=3Dcpp-keyword>public</SPAN>:
    Drive() {
        cout &lt;&lt; <SPAN class=3Dcpp-string>"In Drive"</SPAN> =
&lt;&lt; endl;
        cout &lt;&lt; <SPAN class=3Dcpp-string>"Virtual Pointer =3D =
"</SPAN> &lt;&lt; (<SPAN class=3Dcpp-keyword>int</SPAN>*)<SPAN =
class=3Dcpp-keyword>this</SPAN> &lt;&lt; endl;
        cout &lt;&lt; <SPAN class=3Dcpp-string>"Address of Vtable =3D =
"</SPAN> &lt;&lt; (<SPAN class=3Dcpp-keyword>int</SPAN>*)*(<SPAN =
class=3Dcpp-keyword>int</SPAN>*)<SPAN class=3Dcpp-keyword>this</SPAN> =
&lt;&lt; endl;
        cout &lt;&lt; <SPAN class=3Dcpp-string>"Value at Vtable 1st =
entry =3D "</SPAN> &lt;&lt; (<SPAN =
class=3Dcpp-keyword>int</SPAN>*)*((<SPAN =
class=3Dcpp-keyword>int</SPAN>*)*(<SPAN =
class=3Dcpp-keyword>int</SPAN>*)<SPAN =
class=3Dcpp-keyword>this</SPAN>+<SPAN class=3Dcpp-literal>0</SPAN>) =
&lt;&lt; endl;
        cout &lt;&lt; <SPAN class=3Dcpp-string>"Value at Vtable 2nd =
entry =3D "</SPAN> &lt;&lt; (<SPAN =
class=3Dcpp-keyword>int</SPAN>*)*((<SPAN =
class=3Dcpp-keyword>int</SPAN>*)*(<SPAN =
class=3Dcpp-keyword>int</SPAN>*)<SPAN =
class=3Dcpp-keyword>this</SPAN>+<SPAN class=3Dcpp-literal>1</SPAN>) =
&lt;&lt; endl;
        cout &lt;&lt; endl;
    }
};

<SPAN class=3Dcpp-keyword>class</SPAN> MostDrive : <SPAN =
class=3Dcpp-keyword>public</SPAN> Drive {
<SPAN class=3Dcpp-keyword>public</SPAN>:
    MostDrive() {
        cout &lt;&lt; <SPAN class=3Dcpp-string>"In MostDrive"</SPAN> =
&lt;&lt; endl;
        cout &lt;&lt; <SPAN class=3Dcpp-string>"Virtual Pointer =3D =
"</SPAN> &lt;&lt; (<SPAN class=3Dcpp-keyword>int</SPAN>*)<SPAN =
class=3Dcpp-keyword>this</SPAN> &lt;&lt; endl;
        cout &lt;&lt; <SPAN class=3Dcpp-string>"Address of Vtable =3D =
"</SPAN> &lt;&lt; (<SPAN class=3Dcpp-keyword>int</SPAN>*)*(<SPAN =
class=3Dcpp-keyword>int</SPAN>*)<SPAN class=3Dcpp-keyword>this</SPAN> =
&lt;&lt; endl;
        cout &lt;&lt; <SPAN class=3Dcpp-string>"Value at Vtable 1st =
entry =3D "</SPAN> &lt;&lt; (<SPAN =
class=3Dcpp-keyword>int</SPAN>*)*((<SPAN =
class=3Dcpp-keyword>int</SPAN>*)*(<SPAN =
class=3Dcpp-keyword>int</SPAN>*)<SPAN =
class=3Dcpp-keyword>this</SPAN>+<SPAN class=3Dcpp-literal>0</SPAN>) =
&lt;&lt; endl;
        cout &lt;&lt; <SPAN class=3Dcpp-string>"Value at Vtable 2nd =
entry =3D "</SPAN> &lt;&lt; (<SPAN =
class=3Dcpp-keyword>int</SPAN>*)*((<SPAN =
class=3Dcpp-keyword>int</SPAN>*)*(<SPAN =
class=3Dcpp-keyword>int</SPAN>*)<SPAN =
class=3Dcpp-keyword>this</SPAN>+<SPAN class=3Dcpp-literal>1</SPAN>) =
&lt;&lt; endl;
        cout &lt;&lt; endl;
    }
    <SPAN class=3Dcpp-keyword>virtual</SPAN> <SPAN =
class=3Dcpp-keyword>void</SPAN> f1() { cout &lt;&lt; <SPAN =
class=3Dcpp-string>"MostDrive::f1"</SPAN> &lt;&lt; endl; }
    <SPAN class=3Dcpp-keyword>virtual</SPAN> <SPAN =
class=3Dcpp-keyword>void</SPAN> f2() { cout &lt;&lt; <SPAN =
class=3Dcpp-string>"MostDrive::f2"</SPAN> &lt;&lt; endl; }
};

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

    <SPAN class=3Dcpp-keyword>return</SPAN> <SPAN =
class=3Dcpp-literal>0</SPAN>;
}
</PRE>The output of this program is <PRE>In Base
Virtual Pointer =3D 0012FF7C
Address of Vtable =3D 0046C0D8
Value at Vtable 1st entry =3D 00420F40
Value at Vtable 2nd entry =3D 00420F40

In Drive
Virtual Pointer =3D 0012FF7C
Address of Vtable =3D 0046C0C0
Value at Vtable 1st entry =3D 00420F40
Value at Vtable 2nd entry =3D 00420F40

In MostDrive
Virtual Pointer =3D 0012FF7C
Address of Vtable =3D 0046C0A8
Value at Vtable 1st entry =3D <SPAN class=3Dcpp-literal>00401186</SPAN>
Value at Vtable 2nd entry =3D 004010F5
</PRE>This program shows that both Base and Drive class make their own=20
      virtual table and initialized it with the same value. Now what =
happen if=20
      the inheritance is further deep and none of the class except the =
most=20
      drive overrides any pure virtual function? This happens in the =
case of COM=20
      programming where interfaces are class with only pure virtual =
function and=20
      one interface is inherited from another interface and only =
implementation=20
      class override the pure virtual function of interfaces. Then each =
base=20
      class constructor makes their own vtable and put the same value in =
its=20
      entry. So it means duplication of same code again and again.=20
      <P>The main philosophy of ATL is to make COM component as small as =

      possible, but due to this behavior interface class's constructor =
have lot=20
      of unnecessary code. To solve this problem ATL introduce a macro=20
      <CODE>ATL_NO_VTABLE</CODE> define in ATLDEF.H file as =
</P><PRE><SPAN class=3Dcpp-preprocessor>#define ATL_NO_VTABLE =
__declspec(novtable)</SPAN></PRE>__declspec(novtable)=20
      is Microsoft C++ specific extended attribute of class. When it is =
used=20
      then compiler won't generate the code to initialize the vptr and =
vtable=20
      and reduce the generated code size.=20
      <P>Change our program little bit to better understand this what =
this=20
      attribute can do for us.=20
      <H3>Program 31</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>:
    Base() {
        cout &lt;&lt; <SPAN class=3Dcpp-string>"In Base"</SPAN> &lt;&lt; =
endl;
        cout &lt;&lt; <SPAN class=3Dcpp-string>"Virtual Pointer =3D =
"</SPAN> &lt;&lt; (<SPAN class=3Dcpp-keyword>int</SPAN>*)<SPAN =
class=3Dcpp-keyword>this</SPAN> &lt;&lt; endl;
        cout &lt;&lt; <SPAN class=3Dcpp-string>"Address of Vtable =3D =
"</SPAN> &lt;&lt; (<SPAN class=3Dcpp-keyword>int</SPAN>*)*(<SPAN =
class=3Dcpp-keyword>int</SPAN>*)<SPAN class=3Dcpp-keyword>this</SPAN> =
&lt;&lt; endl;
        cout &lt;&lt; <SPAN class=3Dcpp-string>"Value at Vtable 1st =
entry =3D "</SPAN> &lt;&lt; (<SPAN =
class=3Dcpp-keyword>int</SPAN>*)*((<SPAN =
class=3Dcpp-keyword>int</SPAN>*)*(<SPAN =
class=3Dcpp-keyword>int</SPAN>*)<SPAN =
class=3Dcpp-keyword>this</SPAN>+<SPAN class=3Dcpp-literal>0</SPAN>) =
&lt;&lt; endl;
        cout &lt;&lt; <SPAN class=3Dcpp-string>"Value at Vtable 2nd =
entry =3D "</SPAN> &lt;&lt; (<SPAN =
class=3Dcpp-keyword>int</SPAN>*)*((<SPAN =
class=3Dcpp-keyword>int</SPAN>*)*(<SPAN =
class=3Dcpp-keyword>int</SPAN>*)<SPAN =
class=3Dcpp-keyword>this</SPAN>+<SPAN class=3Dcpp-literal>1</SPAN>) =
&lt;&lt; endl;
        cout &lt;&lt; endl;
    }
    <SPAN class=3Dcpp-keyword>virtual</SPAN> <SPAN =
class=3Dcpp-keyword>void</SPAN> f1() =3D <SPAN =
class=3Dcpp-literal>0</SPAN>;
    <SPAN class=3Dcpp-keyword>virtual</SPAN> <SPAN =
class=3Dcpp-keyword>void</SPAN> f2() =3D <SPAN =
class=3Dcpp-literal>0</SPAN>;
};

<SPAN class=3Dcpp-keyword>class</SPAN> Drive : <SPAN =
class=3Dcpp-keyword>public</SPAN> Base {
<SPAN class=3Dcpp-keyword>public</SPAN>:
    Drive() {
        cout &lt;&lt; <SPAN class=3Dcpp-string>"In Drive"</SPAN> =
&lt;&lt; endl;
        cout &lt;&lt; <SPAN class=3Dcpp-string>"Virtual Pointer =3D =
"</SPAN> &lt;&lt; (<SPAN class=3Dcpp-keyword>int</SPAN>*)<SPAN =
class=3Dcpp-keyword>this</SPAN> &lt;&lt; endl;
        cout &lt;&lt; <SPAN class=3Dcpp-string>"Address of Vtable =3D =
"</SPAN> &lt;&lt; (<SPAN class=3Dcpp-keyword>int</SPAN>*)*(<SPAN =
class=3Dcpp-keyword>int</SPAN>*)<SPAN class=3Dcpp-keyword>this</SPAN> =
&lt;&lt; endl;
        cout &lt;&lt; <SPAN class=3Dcpp-string>"Value at Vtable 1st =
entry =3D "</SPAN> &lt;&lt; (<SPAN =
class=3Dcpp-keyword>int</SPAN>*)*((<SPAN =
class=3Dcpp-keyword>int</SPAN>*)*(<SPAN =
class=3Dcpp-keyword>int</SPAN>*)<SPAN =
class=3Dcpp-keyword>this</SPAN>+<SPAN class=3Dcpp-literal>0</SPAN>) =
&lt;&lt; endl;
        cout &lt;&lt; <SPAN class=3Dcpp-string>"Value at Vtable 2nd =
entry =3D "</SPAN> &lt;&lt; (<SPAN =
class=3Dcpp-keyword>int</SPAN>*)*((<SPAN =
class=3Dcpp-keyword>int</SPAN>*)*(<SPAN =
class=3Dcpp-keyword>int</SPAN>*)<SPAN =
class=3Dcpp-keyword>this</SPAN>+<SPAN class=3Dcpp-literal>1</SPAN>) =
&lt;&lt; endl;
        cout &lt;&lt; endl;
    }
};

<SPAN class=3Dcpp-keyword>class</SPAN> __declspec(novtable) MostDrive : =
<SPAN class=3Dcpp-keyword>public</SPAN> Drive {
<SPAN class=3Dcpp-keyword>public</SPAN>:
    MostDrive() {
        cout &lt;&lt; <SPAN class=3Dcpp-string>"In MostDrive"</SPAN> =
&lt;&lt; endl;
        cout &lt;&lt; <SPAN class=3Dcpp-string>"Virtual Pointer =3D =
"</SPAN> &lt;&lt; (<SPAN class=3Dcpp-keyword>int</SPAN>*)<SPAN =
class=3Dcpp-keyword>this</SPAN> &lt;&lt; endl;
        cout &lt;&lt; <SPAN class=3Dcpp-string>"Address of Vtable =3D =
"</SPAN> &lt;&lt; (<SPAN class=3Dcpp-keyword>int</SPAN>*)*(<SPAN =
class=3Dcpp-keyword>int</SPAN>*)<SPAN class=3Dcpp-keyword>this</SPAN> =
&lt;&lt; endl;
        cout &lt;&lt; <SPAN class=3Dcpp-string>"Value at Vtable 1st =
entry =3D "</SPAN> &lt;&lt; (<SPAN =
class=3Dcpp-keyword>int</SPAN>*)*((<SPAN =
class=3Dcpp-keyword>int</SPAN>*)*(<SPAN =
class=3Dcpp-keyword>int</SPAN>*)<SPAN =
class=3Dcpp-keyword>this</SPAN>+<SPAN class=3Dcpp-literal>0</SPAN>) =
&lt;&lt; endl;
        cout &lt;&lt; <SPAN class=3Dcpp-string>"Value at Vtable 2nd =
entry =3D "</SPAN> &lt;&lt; (<SPAN =
class=3Dcpp-keyword>int</SPAN>*)*((<SPAN =
class=3Dcpp-keyword>int</SPAN>*)*(<SPAN =
class=3Dcpp-keyword>int</SPAN>*)<SPAN =
class=3Dcpp-keyword>this</SPAN>+<SPAN class=3Dcpp-literal>1</SPAN>) =
&lt;&lt; endl;
        cout &lt;&lt; endl;
    }
    <SPAN class=3Dcpp-keyword>virtual</SPAN> <SPAN =
class=3Dcpp-keyword>void</SPAN> f1() { cout &lt;&lt; <SPAN =
class=3Dcpp-string>"MostDrive::f1"</SPAN> &lt;&lt; endl;

⌨️ 快捷键说明

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