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

📄 atl under the hood - part 1.mht

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

<SPAN class=3Dcpp-keyword>int</SPAN> main() {
	CPoint objPoint;
	cout &lt;&lt; "Size of Class =3D " &lt;&lt; <SPAN =
class=3Dcpp-keyword>sizeof</SPAN>(objPoint) &lt;&lt; endl;
	cout &lt;&lt; "Address of Class =3D " &lt;&lt; &amp;objPoint &lt;&lt; =
endl;
	<SPAN class=3Dcpp-keyword>return</SPAN> <SPAN =
class=3Dcpp-literal>0</SPAN>;
}
</PRE>
      <P>The output of the program is </P><PRE>Size of Class =3D <SPAN =
class=3Dcpp-literal>12</SPAN>
Address of Class =3D 0012FF68</PRE>
      <P>The output of these programs shows that when you add any =
virtual=20
      function in the class then its size increases one <CODE><SPAN=20
      class=3Dcpp-keyword>int</SPAN></CODE> size. i.e. in Visual C++ it =
increase=20
      by 4 bytes. It means there are 3 slots for integer in this class =
one for x=20
      one for y and one to handle virtual function that is called a =
virtual=20
      pointer. First take a look at the new slot, namely the virtual =
pointer=20
      that is at the start (or end) the object. To do this we are going =
to=20
      directly access memory occupied by the object. We do this by =
storing the=20
      address of an object in an <CODE><SPAN =
class=3Dcpp-keyword>int</SPAN></CODE>=20
      pointer and using the magic of pointer arithmetic.=20
      <H3>Program 7.</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> CPoint {
<SPAN class=3Dcpp-keyword>public</SPAN>:
	<SPAN class=3Dcpp-keyword>int</SPAN> m_ix;
	<SPAN class=3Dcpp-keyword>int</SPAN> m_iy;
	CPoint(<SPAN class=3Dcpp-keyword>const</SPAN> <SPAN =
class=3Dcpp-keyword>int</SPAN> p_ix =3D <SPAN =
class=3Dcpp-literal>0</SPAN>, <SPAN class=3Dcpp-keyword>const</SPAN> =
<SPAN class=3Dcpp-keyword>int</SPAN> p_iy =3D <SPAN =
class=3Dcpp-literal>0</SPAN>) :=20
		m_ix(p_ix), m_iy(p_iy) {=20
	}
	<SPAN class=3Dcpp-keyword>int</SPAN> getX() <SPAN =
class=3Dcpp-keyword>const</SPAN> {
		<SPAN class=3Dcpp-keyword>return</SPAN> m_ix;
	}
	<SPAN class=3Dcpp-keyword>int</SPAN> getY() <SPAN =
class=3Dcpp-keyword>const</SPAN> {
		<SPAN class=3Dcpp-keyword>return</SPAN> m_iy;
	}
	<SPAN class=3Dcpp-keyword>virtual</SPAN> ~CPoint() { };
};

<SPAN class=3Dcpp-keyword>int</SPAN> main() {
	CPoint objPoint(<SPAN class=3Dcpp-literal>5</SPAN>, <SPAN =
class=3Dcpp-literal>10</SPAN>);

	<SPAN class=3Dcpp-keyword>int</SPAN>* pInt =3D (<SPAN =
class=3Dcpp-keyword>int</SPAN>*)&amp;objPoint;
	*(pInt+<SPAN class=3Dcpp-literal>0</SPAN>) =3D <SPAN =
class=3Dcpp-literal>100</SPAN>;	<SPAN class=3Dcpp-comment>// want to =
change the value of x</SPAN>
	*(pInt+<SPAN class=3Dcpp-literal>1</SPAN>) =3D <SPAN =
class=3Dcpp-literal>200</SPAN>;	<SPAN class=3Dcpp-comment>// want to =
change the value of y</SPAN>

	cout &lt;&lt; "X =3D " &lt;&lt; objPoint.getX() &lt;&lt; endl;
	cout &lt;&lt; "Y =3D " &lt;&lt; objPoint.getY() &lt;&lt; endl;

	<SPAN class=3Dcpp-keyword>return</SPAN> <SPAN =
class=3Dcpp-literal>0</SPAN>;
}
</PRE>
      <P>The important thing in this program is </P><PRE>	<SPAN =
class=3Dcpp-keyword>int</SPAN>* pInt =3D (<SPAN =
class=3Dcpp-keyword>int</SPAN>*)&amp;objPoint;
	*(pInt+<SPAN class=3Dcpp-literal>0</SPAN>) =3D <SPAN =
class=3Dcpp-literal>100</SPAN>;	<SPAN class=3Dcpp-comment>// want to =
change the value of x</SPAN>
	*(pInt+<SPAN class=3Dcpp-literal>1</SPAN>) =3D <SPAN =
class=3Dcpp-literal>200</SPAN>;	<SPAN class=3Dcpp-comment>// want to =
change the value of y</SPAN>
</PRE>In which we treat object as an integer pointer after store its=20
      address in integer pointer. The output of this program is <PRE>X =
=3D <SPAN class=3Dcpp-literal>200</SPAN>
Y =3D <SPAN class=3Dcpp-literal>10</SPAN>
</PRE>
      <P>Of course this is not our required result. This shows when 200 =
is store=20
      in the location where <CODE>m_ix</CODE> data member is resident. =
This=20
      means <CODE>m_ix</CODE> i.e. first member variable, start from =
second=20
      position of the memory not the first. In other words the first =
member is=20
      the virtual pointer and then rest is the data member of the =
object. Just=20
      change the following two lines</P><PRE><SPAN =
class=3Dcpp-keyword>int</SPAN>* pInt =3D (<SPAN =
class=3Dcpp-keyword>int</SPAN>*)&amp;objPoint;
*(pInt+<SPAN class=3Dcpp-literal>1</SPAN>) =3D <SPAN =
class=3Dcpp-literal>100</SPAN>;	<SPAN class=3Dcpp-comment>// want to =
change the value of x</SPAN>
*(pInt+<SPAN class=3Dcpp-literal>2</SPAN>) =3D <SPAN =
class=3Dcpp-literal>200</SPAN>;	<SPAN class=3Dcpp-comment>// want to =
change the value of y</SPAN>
</PRE>
      <P>And we get the required result. Here is the complete program=20
      <H3>Program 8.</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> CPoint {
<SPAN class=3Dcpp-keyword>public</SPAN>:
	<SPAN class=3Dcpp-keyword>int</SPAN> m_ix;
	<SPAN class=3Dcpp-keyword>int</SPAN> m_iy;
	CPoint(<SPAN class=3Dcpp-keyword>const</SPAN> <SPAN =
class=3Dcpp-keyword>int</SPAN> p_ix =3D <SPAN =
class=3Dcpp-literal>0</SPAN>, <SPAN class=3Dcpp-keyword>const</SPAN> =
<SPAN class=3Dcpp-keyword>int</SPAN> p_iy =3D <SPAN =
class=3Dcpp-literal>0</SPAN>) :=20
		m_ix(p_ix), m_iy(p_iy) {=20
	}
	<SPAN class=3Dcpp-keyword>int</SPAN> getX() <SPAN =
class=3Dcpp-keyword>const</SPAN> {
		<SPAN class=3Dcpp-keyword>return</SPAN> m_ix;
	}
	<SPAN class=3Dcpp-keyword>int</SPAN> getY() <SPAN =
class=3Dcpp-keyword>const</SPAN> {
		<SPAN class=3Dcpp-keyword>return</SPAN> m_iy;
	}
	<SPAN class=3Dcpp-keyword>virtual</SPAN> ~CPoint() { };
};

<SPAN class=3Dcpp-keyword>int</SPAN> main() {
	CPoint objPoint(<SPAN class=3Dcpp-literal>5</SPAN>, <SPAN =
class=3Dcpp-literal>10</SPAN>);

	<SPAN class=3Dcpp-keyword>int</SPAN>* pInt =3D (<SPAN =
class=3Dcpp-keyword>int</SPAN>*)&amp;objPoint;
	*(pInt+<SPAN class=3Dcpp-literal>1</SPAN>) =3D <SPAN =
class=3Dcpp-literal>100</SPAN>;	<SPAN class=3Dcpp-comment>// want to =
change the value of x</SPAN>
	*(pInt+<SPAN class=3Dcpp-literal>2</SPAN>) =3D <SPAN =
class=3Dcpp-literal>200</SPAN>;	<SPAN class=3Dcpp-comment>// want to =
change the value of y</SPAN>

	cout &lt;&lt; "X =3D " &lt;&lt; objPoint.getX() &lt;&lt; endl;
	cout &lt;&lt; "Y =3D " &lt;&lt; objPoint.getY() &lt;&lt; endl;

	<SPAN class=3Dcpp-keyword>return</SPAN> <SPAN =
class=3Dcpp-literal>0</SPAN>;
}
</PRE>
      <P>And output of the program is </P><PRE>X =3D <SPAN =
class=3Dcpp-literal>100</SPAN>
Y =3D <SPAN class=3Dcpp-literal>200</SPAN>
</PRE>
      <P>This clearly shows that whenever we add the virtual function =
into the=20
      class then the virtual pointer is added at first location of =
memory=20
      structure.=20
      <P>
      <CENTER><IMG height=3D289=20
      src=3D"http://www.codeproject.com/atl/ATL_UnderTheHood_/CPP1.GIF"=20
      width=3D317></CENTER><BR>Now the question arises: what is stored =
in the=20
      virtual pointer? Take a look at the following program to get an =
idea of=20
      this
      <P></P>
      <H3>Program 9.</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> Class {
	<SPAN class=3Dcpp-keyword>virtual</SPAN> <SPAN =
class=3Dcpp-keyword>void</SPAN> fun() { cout &lt;&lt; "Class::fun" =
&lt;&lt; endl; }
};

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

	cout &lt;&lt; "Address of <SPAN class=3Dcpp-keyword>virtual</SPAN> =
pointer " &lt;&lt; (<SPAN =
class=3Dcpp-keyword>int</SPAN>*)(&amp;objClass+<SPAN =
class=3Dcpp-literal>0</SPAN>) &lt;&lt; endl;
	cout &lt;&lt; "Value at <SPAN class=3Dcpp-keyword>virtual</SPAN> =
pointer " &lt;&lt; (<SPAN class=3Dcpp-keyword>int</SPAN>*)*(<SPAN =
class=3Dcpp-keyword>int</SPAN>*)(&amp;objClass+<SPAN =
class=3Dcpp-literal>0</SPAN>) &lt;&lt; endl;
	<SPAN class=3Dcpp-keyword>return</SPAN> <SPAN =
class=3Dcpp-literal>0</SPAN>;
}
</PRE>
      <P>The output of this program is </P><PRE>Address of <SPAN =
class=3Dcpp-keyword>virtual</SPAN> pointer 0012FF7C
Value at <SPAN class=3Dcpp-keyword>virtual</SPAN> pointer 0046C060
</PRE>
      <P>The virtual pointer stores the address of a table that is =
called the=20
      virtual table. And a virtual table stores address of all the =
virtual=20
      functions of that class. In other words the virtual table is an =
array of=20
      addresses of virtual functions. Let's take a look at the following =
program=20
      to get an idea of it.=20
      <H3>Program 10.</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> Class {
	<SPAN class=3Dcpp-keyword>virtual</SPAN> <SPAN =
class=3Dcpp-keyword>void</SPAN> fun() { cout &lt;&lt; "Class::fun" =
&lt;&lt; endl; }
};

<SPAN class=3Dcpp-keyword>typedef</SPAN> <SPAN =
class=3Dcpp-keyword>void</SPAN> (*Fun)(<SPAN =
class=3Dcpp-keyword>void</SPAN>);

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

	cout &lt;&lt; "Address of <SPAN class=3Dcpp-keyword>virtual</SPAN> =
pointer " &lt;&lt; (<SPAN =
class=3Dcpp-keyword>int</SPAN>*)(&amp;objClass+<SPAN =
class=3Dcpp-literal>0</SPAN>) &lt;&lt; endl;
	cout &lt;&lt; "Value at <SPAN class=3Dcpp-keyword>virtual</SPAN> =
pointer i.e. Address of <SPAN class=3Dcpp-keyword>virtual</SPAN> table " =

		 &lt;&lt; (<SPAN class=3Dcpp-keyword>int</SPAN>*)*(<SPAN =
class=3Dcpp-keyword>int</SPAN>*)(&amp;objClass+<SPAN =
class=3Dcpp-literal>0</SPAN>) &lt;&lt; endl;
	cout &lt;&lt; "Value at first entry of <SPAN =
class=3Dcpp-keyword>virtual</SPAN> table "=20
		 &lt;&lt; (<SPAN class=3Dcpp-keyword>int</SPAN>*)*(<SPAN =
class=3Dcpp-keyword>int</SPAN>*)*(<SPAN =
class=3Dcpp-keyword>int</SPAN>*)(&amp;objClass+<SPAN =
class=3Dcpp-literal>0</SPAN>) &lt;&lt; endl;

	cout &lt;&lt; endl &lt;&lt; "Executing <SPAN =
class=3Dcpp-keyword>virtual</SPAN> function" &lt;&lt; endl &lt;&lt; =
endl;
	Fun pFun =3D (Fun)*(<SPAN class=3Dcpp-keyword>int</SPAN>*)*(<SPAN =
class=3Dcpp-keyword>int</SPAN>*)(&amp;objClass+<SPAN =
class=3Dcpp-literal>0</SPAN>);
	pFun();
	<SPAN class=3Dcpp-keyword>return</SPAN> <SPAN =
class=3Dcpp-literal>0</SPAN>;
}
</PRE>
      <P>This program has some uncommon indirection with typecast. The =
most=20
      important line of this program is </P><PRE>	Fun pFun =3D =
(Fun)*(<SPAN class=3Dcpp-keyword>int</SPAN>*)*(<SPAN =
class=3Dcpp-keyword>int</SPAN>*)(&amp;objClass+<SPAN =
class=3Dcpp-literal>0</SPAN>);
</PRE>Here <CODE>Fun </CODE>is a <CODE><SPAN=20
      class=3Dcpp-keyword>typedef</SPAN></CODE>'d function pointer. =
<PRE>	<SPAN class=3Dcpp-keyword>typedef</SPAN> <SPAN =
class=3Dcpp-keyword>void</SPAN> (*Fun)(<SPAN =
class=3Dcpp-keyword>void</SPAN>);
</PRE>
      <P>Let's dissect the lengthy uncommon indirection. <CODE>(<SPAN=20
      class=3Dcpp-keyword>int</SPAN>*)(&amp;objClass+<SPAN=20
      class=3Dcpp-literal>0</SPAN>) </CODE>gives the address of the =
virtual=20
      pointer of the class which is the first entry in the class and we =
typecast=20
      it to <CODE><SPAN class=3Dcpp-keyword>int</SPAN>*</CODE>. To get =
the value=20
      at this address we use the indirection operator (i.e. =
<CODE>*</CODE>) and=20
      then again typecast it to <CODE><SPAN =
class=3Dcpp-keyword>int</SPAN>*</CODE>=20
      i.e. <CODE>(<SPAN class=3Dcpp-keyword>int</SPAN>*)*(<SPAN=20
      class=3Dcpp-keyword>int</SPAN>*)(&amp;objClass+<SPAN=20
      class=3Dcpp-literal>0</SPAN>)</CODE>. This will give the address =
of first=20
      entry of the virtual table. To get the value at this location, =
i.e. get=20
      the address of first virtual function of the class again use the=20
      indirection operator and now typecast to the appropriate function =
pointer=20
      type. So </P><PRE>	Fun pFun =3D (Fun)*(<SPAN =
class=3Dcpp-keyword>int</SPAN>*)*(<SPAN =
class=3Dcpp-keyword>int</SPAN>*)(&amp;objClass+<SPAN =
class=3Dcpp-literal>0</SPAN>);</PRE>
      <P>Means get the value from the first entry of the virtual table =
and store=20
      it in pFun after typecast it into the Fun type.=20
      <CENTER><IMG height=3D92=20
      src=3D"http://www.codeproject.com/atl/ATL_UnderTheHood_/CPP2.GIF"=20
      width=3D400></CENTER><BR>What happen when one more virtual =
function add in=20
      the class. Now we want to access second member of the virtual =
table. Take=20
      a look at the following program to see the values at virtual table =

      <H3>Program 11.</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> Class {
	<SPAN class=3Dcpp-keyword>virtual</SPAN> <SPAN =
class=3Dcpp-keyword>void</SPAN> f() { cout &lt;&lt; "Class::f" &lt;&lt; =
endl; }
	<SPAN class=3Dcpp-keyword>virtual</SPAN> <SPAN =
class=3Dcpp-keyword>void</SPAN> g() { cout &lt;&lt; "Class::g" &lt;&lt; =
endl; }
};

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

	cout &lt;&lt; "Address of <SPAN class=3Dcpp-keyword>virtual</SPAN> =
pointer " &lt;&lt; (<SPAN =
class=3Dcpp-keyword>int</SPAN>*)(&amp;objClass+<SPAN =
class=3Dcpp-literal>0</SPAN>) &lt;&lt; endl;
	cout &lt;&lt; "Value at <SPAN class=3Dcpp-keyword>virtual</SPAN> =
pointer i.e. Address of <SPAN class=3Dcpp-keyword>virtual</SPAN> table " =

⌨️ 快捷键说明

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