﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-xiaoguozi's Blog-随笔分类-编程语言</title><link>http://www.cppblog.com/guojingjia2006/category/11666.html</link><description>Pay it forword - 我并不觉的自豪，我所尝试的事情都失败了······习惯原本生活的人不容易改变，就算现状很糟，他们也很难改变，在过程中，他们还是放弃了······他们一放弃，大家就都是输家······让爱传出去，很困难，也无法预料，人们需要更细心的观察别人，要随时注意才能保护别人，因为他们未必知道自己要什么·····</description><language>zh-cn</language><lastBuildDate>Tue, 21 Jan 2014 03:04:15 GMT</lastBuildDate><pubDate>Tue, 21 Jan 2014 03:04:15 GMT</pubDate><ttl>60</ttl><item><title>CentOS 6下安装nodejs 0.9.0</title><link>http://www.cppblog.com/guojingjia2006/archive/2014/01/20/205486.html</link><dc:creator>小果子</dc:creator><author>小果子</author><pubDate>Mon, 20 Jan 2014 02:11:00 GMT</pubDate><guid>http://www.cppblog.com/guojingjia2006/archive/2014/01/20/205486.html</guid><wfw:comment>http://www.cppblog.com/guojingjia2006/comments/205486.html</wfw:comment><comments>http://www.cppblog.com/guojingjia2006/archive/2014/01/20/205486.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/guojingjia2006/comments/commentRss/205486.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/guojingjia2006/services/trackbacks/205486.html</trackback:ping><description><![CDATA[<div><div id="cnblogs_post_body"><p>确保安装了python，大部分安装失败都是由于python版本过低导致。安装之前，升级python版本，升级步骤 <a href="http://www.tomtalk.net/wiki/Python">http://www.tomtalk.net/wiki/Python</a>。</p>  <p>[root@SNDA-192-168-15-161 ~]# python -V   <br />Python 2.7.3    <br />开始安装：</p>  <p>1).下载nodejs到本地并解压缩   <br />[root@SNDA-192-168-15-161 node]# wget http://nodejs.org/dist/v0.9.0/node-v0.9.0.tar.gz    <br />[root@SNDA-192-168-15-161 node]# tar zxvf node-v0.9.0.tar.gz    <br />2).进入到该目录编译和安装    <br />[root@SNDA-192-168-15-161 node-v0.9.0]# cd node-v0.9.0    <br />[root@SNDA-192-168-15-161&nbsp; node-v0.9.0]# ./configure --prefix=/usr/local/node/0.9.0    <br />这里安装在了/usr/local/node/0.9.0目录下    <br />[root@SNDA-192-168-15-161 node-v0.9.0]# make    <br />[root@SNDA-192-168-15-161 node-v0.9.0]# make install    <br />3).配置NODE_HOME    <br />[root@SNDA-192-168-15-161 node-v0.9.0]# vi /etc/profile    <br />在export PATH USER 。。。一行的上面添加如下内容，并将NODE_HOME/bin设置到系统path中    <br />#set for nodejs    <br />export NODE_HOME=/usr/local/node/0.9.0    <br />export PATH=$NODE_HOME/bin:$PATH    <br />保存退出后执行如下命令，使刚才的配置生效    <br />[root@SNDA-192-168-15-161 node-v0.9.0]# source /etc/profile</p>  <p>执行node -h命令验证设置成功</p>  <p>[root@SNDA-192-168-15-161 ~]# node -h   <br />Usage: node [options] [ -e script | script.js ] [arguments]    <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; node debug script.js [arguments] </p>  <p>Options:   <br />&nbsp; -v, --version&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; print node's version    <br />&nbsp; -e, --eval script&nbsp;&nbsp;&nbsp; evaluate script    <br />&nbsp; -p, --print&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; print result of --eval    <br />&nbsp; -i, --interactive&nbsp;&nbsp;&nbsp; always enter the REPL even if stdin    <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; does not appear to be a terminal    <br />&nbsp; --no-deprecation&nbsp;&nbsp;&nbsp;&nbsp; silence deprecation warnings    <br />&nbsp; --trace-deprecation&nbsp; show stack traces on deprecations    <br />&nbsp; --v8-options&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; print v8 command line options    <br />&nbsp; --max-stack-size=val set max v8 stack size (bytes) </p>  <p>Environment variables:   <br />NODE_PATH&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ':'-separated list of directories    <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; prefixed to the module search path.    <br />NODE_MODULE_CONTEXTS&nbsp;&nbsp; Set to 1 to load modules in their own    <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; global contexts.    <br />NODE_DISABLE_COLORS&nbsp;&nbsp;&nbsp; Set to 1 to disable colors in the REPL </p>  <p>Documentation can be found at <a href="http://nodejs.org/">http://nodejs.org/</a>    <br />至此安装设置完毕。</p>  <p>运行一个简单的node应用程序 + socket.io，首先需要安装socket.io模块</p>  <p>[root@SNDA-192-168-15-161 ~]# npm install socket.io</p>  <p>[root@SNDA-192-168-15-161 ~]# vi app.js</p>  <p>var http=require('http');   <br />var io =require('socket.io');    <br />var server = http.createServer(function(req,res){ </p>  <p>&nbsp;&nbsp;&nbsp; res.writeHead(200,{'Content-Type':'text/plain'});   <br />&nbsp;&nbsp;&nbsp; res.end('Hello world');    <br />}); </p>  <p>server.listen(process.argv[2]); </p>  <p>var socket = io.listen(server);   <br />socket.on('connection',function(client){    <br />&nbsp;&nbsp;&nbsp; console.log('client has connected');    <br />&nbsp;&nbsp;&nbsp; client.on('message',function(){ });    <br />});    <br />&nbsp;</p>  <p>[root@SNDA-192-168-15-161 ~]# nodejs ./app.js 8001 &amp;</p>  <p>[root@SNDA-192-168-15-161 ~]# nodejs ./app.js 8002 &amp;</p>  <p>[root@SNDA-192-168-15-161 ~]# nodejs ./app.js 8003 &amp;</p>  <p>[root@SNDA-192-168-15-161 ~]# nodejs ./app.js 8004 &amp;</p>  <p>更详细的参照<a href="http://socket.io/#how-to-use">socket.io的官网</a>的例子。 </p>  <p><a href="http://cnodejs.org/topic/4f16442ccae1f4aa27001139" target="_blank">websocket与node.js的完美结合</a></p>  <p><a title="http://wanshuiqianshan.iteye.com/blog/1618498" href="http://wanshuiqianshan.iteye.com/blog/1618498">http://wanshuiqianshan.iteye.com/blog/1618498</a></p></div></div><img src ="http://www.cppblog.com/guojingjia2006/aggbug/205486.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/guojingjia2006/" target="_blank">小果子</a> 2014-01-20 10:11 <a href="http://www.cppblog.com/guojingjia2006/archive/2014/01/20/205486.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>单实例模板类(一次面试经历)</title><link>http://www.cppblog.com/guojingjia2006/archive/2010/09/10/126292.html</link><dc:creator>小果子</dc:creator><author>小果子</author><pubDate>Fri, 10 Sep 2010 02:30:00 GMT</pubDate><guid>http://www.cppblog.com/guojingjia2006/archive/2010/09/10/126292.html</guid><wfw:comment>http://www.cppblog.com/guojingjia2006/comments/126292.html</wfw:comment><comments>http://www.cppblog.com/guojingjia2006/archive/2010/09/10/126292.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/guojingjia2006/comments/commentRss/126292.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/guojingjia2006/services/trackbacks/126292.html</trackback:ping><description><![CDATA[<div style="background-color: #eeeeee; font-size: 13px; border: 1px solid #cccccc; padding: 4px 5px 4px 4px; width: 98%; font-family: courier new;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000;">template</span><span style="color: #000000;">&lt;</span><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;T</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"><br></span><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;Singleton{<br></span><span style="color: #0000ff;">public</span><span style="color: #000000;">:<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">static</span><span style="color: #000000;">&nbsp;T</span><span style="color: #000000;">*</span><span style="color: #000000;">&nbsp;getInstance(){<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">(ptr</span><span style="color: #000000;">==</span><span style="color: #000000;">NULL){<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ptr</span><span style="color: #000000;">=</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;T();</span><span style="color: #008000;">//</span><span style="color: #008000;">(T*)(::operator&nbsp;new(sizeof(T)));</span><span style="color: #008000;"><br></span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;ptr;<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br></span><span style="color: #0000ff;">private</span><span style="color: #000000;">:<br>&nbsp;&nbsp;&nbsp;&nbsp;Singleton(){};<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">static</span><span style="color: #000000;">&nbsp;T</span><span style="color: #000000;">*</span><span style="color: #000000;">&nbsp;ptr;<br>};<br>template</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">typename&nbsp;T</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"><br>T</span><span style="color: #000000;">*</span><span style="color: #000000;">&nbsp;Singleton</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">T</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">::ptr</span><span style="color: #000000;">=</span><span style="color: #000000;">0</span><span style="color: #000000;">;<br><br>class C{<br>public:<br>&nbsp;&nbsp;&nbsp; int x;<br>&nbsp;&nbsp;&nbsp; C(){<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; x=0;<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; ~C(){<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; cout&lt;&lt;"C delete"&lt;&lt;endl;<br>&nbsp;&nbsp;&nbsp; }<br>};<br><br></span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;main(){<br>&nbsp;&nbsp;&nbsp;&nbsp;C</span><span style="color: #000000;">*</span><span style="color: #000000;">&nbsp;c</span><span style="color: #000000;">=</span><span style="color: #000000;">Singleton</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">C</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">::getInstance();<br>&nbsp;&nbsp;&nbsp;&nbsp;C</span><span style="color: #000000;">*</span><span style="color: #000000;">&nbsp;d</span><span style="color: #000000;">=</span><span style="color: #000000;">Singleton</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">C</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">::getInstance();<br><br>&nbsp;&nbsp;&nbsp;&nbsp;cout</span><span style="color: #000000;">&lt;&lt;</span><span style="color: #000000;">c</span><span style="color: #000000;">&lt;&lt;</span><span style="color: #000000;">"</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">&lt;&lt;</span><span style="color: #000000;">d</span><span style="color: #000000;">&lt;&lt;</span><span style="color: #000000;">endl;<br>}</span></div>
<br>当时一时没反应过来，用的较多的还是实例化的单体类.这里笔记一下。不过模板类有其自己方便的地方。所以还是有必要的.<br>   <img src ="http://www.cppblog.com/guojingjia2006/aggbug/126292.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/guojingjia2006/" target="_blank">小果子</a> 2010-09-10 10:30 <a href="http://www.cppblog.com/guojingjia2006/archive/2010/09/10/126292.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>c++ 虚函数表(转）</title><link>http://www.cppblog.com/guojingjia2006/archive/2010/05/13/115300.html</link><dc:creator>小果子</dc:creator><author>小果子</author><pubDate>Thu, 13 May 2010 10:37:00 GMT</pubDate><guid>http://www.cppblog.com/guojingjia2006/archive/2010/05/13/115300.html</guid><wfw:comment>http://www.cppblog.com/guojingjia2006/comments/115300.html</wfw:comment><comments>http://www.cppblog.com/guojingjia2006/archive/2010/05/13/115300.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/guojingjia2006/comments/commentRss/115300.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/guojingjia2006/services/trackbacks/115300.html</trackback:ping><description><![CDATA[<div style="font-family: courier new;" class="postText">
<p>C++中的虚函数的作用主要是实现了多态的机制。关于多态，简而言之就是用父类型别的指针指向其子类的实例，然后通过父类的指针调用实际子类的
成员函数。这种技术可以让父类的指针有&#8220;多种形态&#8221;，这是一种泛型技术。所谓泛型技术，说白了就是试图使用不变的代码来实现可变的算法。比如：模板技
术，RTTI技术，虚函数技术，要么是试图做到在编译时决议，要么试图做到运行时决议。
</p>
<p>关于虚函数的使用方法，我在这里不做过多的阐述。大家可以看看相关的C++的书籍。在这篇文章中，我只想从虚函数的实现机制上面为大家
一个清晰的剖析。
</p>
<p>当然，相同的文章在网上也出现过一些了，但我总感觉这些文章不是很容易阅读，大段大段的代码，没有图片，没有详细的说明，没有比较，没有举
一反三。不利于学习和阅读，所以这是我想写下这篇文章的原因。也希望大家多给我提意见。
</p>
<p>言归正传，让我们一起进入虚函数的世界。
</p>
<h3>虚函数表</h3>
<p>对C++ 了解的人都应该知道虚函数（Virtual Function）是通过一张虚函数表（Virtual
Table）来实现的。简称为V-Table。
在这个表中，主是要一个类的虚函数的地址表，这张表解决了继承、覆盖的问题，保证其容真实反应实际的函数。这样，在有虚函数的类的实例中这个表被分配在了
这个实例的内存中，所以，当我们用父类的指针来操作一个子类的时候，这张虚函数表就显得由为重要了，它就像一个地图一样，指明了实际所应该调用的函数。
</p>
<p>这里我们着重看一下这张虚函数表。在C++的标准规格说明书中说到，编译器必需要保证虚函数表的指针存在于对象实例中最前面的位置（这是为
了保证正确取到虚函数的偏移量）。 这意味着我们通过对象实例的地址得到这张虚函数表，然后就可以遍历其中函数指针，并调用相应的函数。
</p>
<p>听我扯了那么多，我可以感觉出来你现在可能比以前更加晕头转向了。 没关系，下面就是实际的例子，相信聪明的你一看就明白了。
</p>
<p>假设我们有这样的一个类：
</p>
<p>class Base {
</p>
<p>public:
</p>
<p>virtual void f() { cout &lt;&lt; "Base::f" &lt;&lt; endl; }
</p>
<p>virtual void g() { cout &lt;&lt; "Base::g" &lt;&lt; endl; }
</p>
<p>virtual void h() { cout &lt;&lt; "Base::h" &lt;&lt; endl; }
</p>
<p>};
</p>
<p>按照上面的说法，我们可以通过Base的实例来得到虚函数表。 下面是实际例程：
</p>
<p>typedef void(*Fun)(void);
</p>
<p>Base b;
</p>
<p>Fun pFun = NULL;
</p>
<p>cout &lt;&lt; "虚函数表地址：" &lt;&lt; (int*)(&amp;b) &lt;&lt; endl;
</p>
<p>cout &lt;&lt; "虚函数表 — 第一个函数地址：" &lt;&lt; (int*)*(int*)(&amp;b)
&lt;&lt; endl;
</p>
<p>// Invoke the first virtual function
</p>
<p>pFun = (Fun)*((int*)*(int*)(&amp;b));
</p>
<p>pFun();
</p>
<p>实际运行经果如下：(Windows XP+VS2003, Linux 2.6.22 + GCC 4.1.3)
</p>
<p>虚函数表地址：0012FED4
</p>
<p>虚函数表 — 第一个函数地址：0044F148
</p>
<p>Base::f
</p>
<p>通过这个示例，我们可以看到，我们可以通过强行把&amp;b转成int
*，取得虚函数表的地址，然后，再次取址就可以得到第一个虚函数的地址了，也就是Base::f()，这在上面的程序中得到了验证（把int*
强制转成了函数指针）。通过这个示例，我们就可以知道如果要调用Base::g()和Base::h()，其代码如下：
</p>
<p>(Fun)*((int*)*(int*)(&amp;b)+0); // Base::f()
</p>
<p>(Fun)*((int*)*(int*)(&amp;b)+1); // Base::g()
</p>
<p>(Fun)*((int*)*(int*)(&amp;b)+2); // Base::h()
</p>
<p>这个时候你应该懂了吧。什么？还是有点晕。也是，这样的代码看着太乱了。没问题，让我画个图解释一下。如下所示：
</p>
<p><img  src="http://p.blog.csdn.net/images/p_blog_csdn_net/haoel/15190/o_vtable1.jpg" border="0">
</p>
<p>注意：在上面这个图中，我在虚函数表的最后多加了一个结点，这是虚函数表的结束结点，就像字符串的结束符&#8220;\0&#8221;一样，其标志了虚函数表的
结束。这个结束标志的值在不同的编译器下是不同的。在WinXP+VS2003下，这个值是NULL。而在Ubuntu 7.10 + Linux
2.6.22 + GCC 4.1.3下，这个值是如果1，表示还有下一个虚函数表，如果值是0，表示是最后一个虚函数表。
</p>
<p>下面，我将分别说明&#8220;无覆盖&#8221;和&#8220;有覆盖&#8221;时的虚函数表的样子。没有覆盖父类的虚函数是毫无意义的。我之所以要讲述没有覆盖的情况，主要目
的是为了给一个对比。在比较之下，我们可以更加清楚地知道其内部的具体实现。
</p>
<h3>一般继承（无虚函数覆盖）</h3>
<p>下面，再让我们来看看继承时的虚函数表是什么样的。假设有如下所示的一个继承关系：
</p>
<p><img  src="http://p.blog.csdn.net/images/p_blog_csdn_net/haoel/15190/o_Drawing3.jpg" border="0">
</p>
<p>请注意，在这个继承关系中，子类没有重载任何父类的函数。那么，在派生类的实例中，其虚函数表如下所示：
</p>
<p>对于实例：Derive d; 的虚函数表如下：
</p>
<p><img  src="http://p.blog.csdn.net/images/p_blog_csdn_net/haoel/15190/o_vtable2.JPG" border="0">
</p>
<p>我们可以看到下面几点：
</p>
<p>1）虚函数按照其声明顺序放于表中。
</p>
<p>2）父类的虚函数在子类的虚函数前面。
</p>
<p>我相信聪明的你一定可以参考前面的那个程序，来编写一段程序来验证。
</p>
<h3>一般继承（有虚函数覆盖）</h3>
<p>覆盖父类的虚函数是很显然的事情，不然，虚函数就变得毫无意义。下面，我们来看一下，如果子类中有虚函数重载了父类的虚函数，会是一个什么样子？假
设，我们有下面这样的一个继承关系。
</p>
<p><img  src="http://p.blog.csdn.net/images/p_blog_csdn_net/haoel/15190/o_Drawing4.jpg" border="0">
</p>
<p>为了让大家看到被继承过后的效果，在这个类的设计中，我只覆盖了父类的一个函数：f()。那么，对于派生类的实例，其虚函数表会是下面的一
个样子：
</p>
<p><img  src="http://p.blog.csdn.net/images/p_blog_csdn_net/haoel/15190/o_vtable3.JPG" border="0">
</p>
<p>我们从表中可以看到下面几点，
</p>
<p>1）覆盖的f()函数被放到了虚表中原来父类虚函数的位置。
</p>
<p>2）没有被覆盖的函数依旧。
</p>
<p>这样，我们就可以看到对于下面这样的程序，
</p>
<p>Base *b = new Derive();
</p>
<p>b-&gt;f();
</p>
<p>由b所指的内存中的虚函数表的f()的位置已经被Derive::f()函数地址所取代，于是在实际调用发生时，是Derive::f()
被调用了。这就实现了多态。
</p>
<h3>多重继承（无虚函数覆盖）</h3>
<p>下面，再让我们来看看多重继承中的情况，假设有下面这样一个类的继承关系。注意：子类并没有覆盖父类的函数。
</p>
<p><img  src="http://p.blog.csdn.net/images/p_blog_csdn_net/haoel/15190/o_Drawing1.jpg" border="0">
</p>
<p>对于子类实例中的虚函数表，是下面这个样子：
</p>
<p><img  src="http://p.blog.csdn.net/images/p_blog_csdn_net/haoel/15190/o_vtable4.JPG" border="0">
</p>
<p>我们可以看到：
</p>
<p>1） 每个父类都有自己的虚表。
</p>
<p>2） 子类的成员函数被放到了第一个父类的表中。（所谓的第一个父类是按照声明顺序来判断的）
</p>
<p>这样做就是为了解决不同的父类类型的指针指向同一个子类实例，而能够调用到实际的函数。
</p>
<h3>多重继承（有虚函数覆盖）</h3>
<p>下面我们再来看看，如果发生虚函数覆盖的情况。
</p>
<p>下图中，我们在子类中覆盖了父类的f()函数。
</p>
<p><img  src="http://p.blog.csdn.net/images/p_blog_csdn_net/haoel/15190/o_Drawing2.jpg" border="0">
</p>
<p>下面是对于子类实例中的虚函数表的图：
</p>
<p><img  src="http://p.blog.csdn.net/images/p_blog_csdn_net/haoel/15190/o_vtable5.jpg" border="0">
</p>
<p>我们可以看见，三个父类虚函数表中的f()的位置被替换成了子类的函数指针。这样，我们就可以任一静态类型的父类来指向子类，并调用子类的
f()了。如：
</p>
<p>Derive d;
</p>
<p>Base1 *b1 = &amp;d;
</p>
<p>Base2 *b2 = &amp;d;
</p>
<p>Base3 *b3 = &amp;d;
</p>
<p>b1-&gt;f(); //Derive::f()
</p>
<p>b2-&gt;f(); //Derive::f()
</p>
<p>b3-&gt;f(); //Derive::f()
</p>
<p>b1-&gt;g(); //Base1::g()
</p>
<p>b2-&gt;g(); //Base2::g()
</p>
<p>b3-&gt;g(); //Base3::g()
</p>
<h3>安全性</h3>
<p>每次写C++的文章，总免不了要批判一下C++。这篇文章也不例外。通过上面的讲述，相信我们对虚函数表有一个比较细致的了解了。水可载舟，亦可覆
舟。下面，让我们来看看我们可以用虚函数表来干点什么坏事吧。
</p>
<p><strong>一、通过父类型的指针访问子类自己的虚函数</strong>
</p>
<p>我们知道，子类没有重载父类的虚函数是一件毫无意义的事情。因为多态也是要基于函数重载的。虽然在上面的图中我们可以看到Base1的虚表
中有Derive的虚函数，但我们根本不可能使用下面的语句来调用子类的自有虚函数：
</p>
<p>Base1 *b1 = new Derive();
</p>
<p>b1-&gt;f1(); //编译出错
</p>
<p>任何妄图使用父类指针想调用子类中的<strong>未覆盖父类的成员函数</strong>的行为都会被编译器视为非法，所以，这样的程
序根本无法编译通过。但在运行时，我们可以通过指针的方式访问虚函数表来达到违反C++语义的行为。（关于这方面的尝试，通过阅读后面附录的代码，相信你
可以做到这一点）
</p>
<p><strong>二、访问non-public</strong><strong>的虚函数</strong>
</p>
<p>另外，如果父类的虚函数是private或是protected的，但这些非public的虚函数同样会存在于虚函数表中，所以，我们同样
可以使用访问虚函数表的方式来访问这些non-public的虚函数，这是很容易做到的。
</p>
<p>如：
</p>
<p>class Base {
</p>
<p>private:
</p>
<p>virtual void f() { cout &lt;&lt; "Base::f" &lt;&lt; endl; }
</p>
<p>};
</p>
<p>class Derive : public Base{
</p>
<p>};
</p>
<p>typedef void(*Fun)(void);
</p>
<p>void main() {
</p>
<p>Derive d;
</p>
<p>Fun pFun = (Fun)*((int*)*(int*)(&amp;d)+0);
</p>
<p>pFun();
</p>
<p>}
</p>
<h3>结束语</h3>
<p>C++这门语言是一门Magic的语言，对于程序员来说，我们似乎永远摸不清楚这门语言背着我们在干了什么。需要熟悉这门语言，我们就必需要了解
C++里面的那些东西，需要去了解C++中那些危险的东西。不然，这是一种搬起石头砸自己脚的编程语言。</p>
</div><img src ="http://www.cppblog.com/guojingjia2006/aggbug/115300.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/guojingjia2006/" target="_blank">小果子</a> 2010-05-13 18:37 <a href="http://www.cppblog.com/guojingjia2006/archive/2010/05/13/115300.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>