<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Yoichi Kawasaki blog &#187; gcc</title>
	<atom:link href="http://yk55.com/blog/tags/gcc/feed/" rel="self" type="application/rss+xml" />
	<link>http://yk55.com/blog</link>
	<description>the place to organize and record my ideas ...</description>
	<lastBuildDate>Sat, 28 Aug 2010 03:47:26 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.6</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Dynamic Binding &amp; VTable Concept in C++</title>
		<link>http://yk55.com/blog/2010/02/27/dynamic-binding-vtable-concept/</link>
		<comments>http://yk55.com/blog/2010/02/27/dynamic-binding-vtable-concept/#comments</comments>
		<pubDate>Sat, 27 Feb 2010 10:32:11 +0000</pubDate>
		<dc:creator>yoichi</dc:creator>
				<category><![CDATA[Programming / プログラミング]]></category>
		<category><![CDATA[cplusplus]]></category>
		<category><![CDATA[gcc]]></category>
		<category><![CDATA[polymorphism]]></category>
		<category><![CDATA[vpointer]]></category>
		<category><![CDATA[vtable]]></category>

		<guid isPermaLink="false">http://yk55.com/blog/?p=197</guid>
		<description><![CDATA[たまにc++コードのコンパイル時にエラー文言でvtableというキーワードを見たことはないだろうか？Polymorphismという有名なワードに対しこのvtableはあまりにも目立たない存在だ。とはいえPolymorphismを実現するためになくてはならない（最）重要なポジションを占めているのがvtable。別にvtableを理解しなくともPolymorphismの理解はできる。 ただし、骨太になりたいのならばPolymorphismを実現するためにどのようにvtableが使われているのかを理解しておくべきである。
UPCASTING
Virtual関数との比較のためにVirtual関数を持たないクラス継承を説明する。以下のようにvirtual関数を持たないSuperClassをSubClassが継承する。 SuperClassを継承したSubClassの参照をSuperClassポインタ変数に入れた場合は、子クラスへの参照がUPCASTされ親クラスへの参照として扱われる。実行結果はSuperClassへの参照へとUPCASTされるのでSuperClassの関数の内容が表示される。
#include &#60;iostream&#62;
using std::cout;
using std::endl;
class SuperClass &#123;
public:
&#160; &#160; void func&#40;&#41; &#123; cout &#60;&#60; &#34;SuperClass::func()&#34; &#60;&#60; endl; &#125;
&#125;;
class SubClass : public SuperClass &#123;
public:
&#160; &#160; void func&#40;&#41; &#123; cout &#60;&#60; &#34;SubClass::func()&#34; &#60;&#60; endl; &#125;
&#125;;
int main&#40;int argc, char **argv &#41; &#123;
&#160; &#160; &#160;SubClass sub;
&#160; &#160; &#160;SuperClass *super =&#38;sub; 
&#160; &#160; &#160;super-&#62;func&#40;&#41;;
&#160; &#160; &#160;return 0;
&#125;
[実行結果]
SuperClass::func()
VIRTUAL FUNCTION, VTABLE, and [...]]]></description>
			<content:encoded><![CDATA[<p>たまにc++コードのコンパイル時にエラー文言でvtableというキーワードを見たことはないだろうか？Polymorphismという有名なワードに対しこのvtableはあまりにも目立たない存在だ。とはいえPolymorphismを実現するためになくてはならない（最）重要なポジションを占めているのがvtable。別にvtableを理解しなくともPolymorphismの理解はできる。 ただし、骨太になりたいのならばPolymorphismを実現するためにどのようにvtableが使われているのかを理解しておくべきである。</p>
<h2>UPCASTING</h2>
<p>Virtual関数との比較のためにVirtual関数を持たないクラス継承を説明する。以下のようにvirtual関数を持たないSuperClassをSubClassが継承する。 SuperClassを継承したSubClassの参照をSuperClassポインタ変数に入れた場合は、子クラスへの参照がUPCASTされ親クラスへの参照として扱われる。実行結果はSuperClassへの参照へとUPCASTされるのでSuperClassの関数の内容が表示される。</p>
<div class="codecolorer-container c default" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;"><div class="c codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #339933;">#include &lt;iostream&gt;</span><br />
using std<span style="color: #339933;">::</span><a href="http://www.opengroup.org/onlinepubs/009695399/functions/cout.html"><span style="color: #000066;">cout</span></a><span style="color: #339933;">;</span><br />
using std<span style="color: #339933;">::</span><span style="color: #202020;">endl</span><span style="color: #339933;">;</span><br />
class SuperClass <span style="color: #009900;">&#123;</span><br />
public<span style="color: #339933;">:</span><br />
&nbsp; &nbsp; <span style="color: #993333;">void</span> func<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> <a href="http://www.opengroup.org/onlinepubs/009695399/functions/cout.html"><span style="color: #000066;">cout</span></a> <span style="color: #339933;">&lt;&lt;</span> <span style="color: #ff0000;">&quot;SuperClass::func()&quot;</span> <span style="color: #339933;">&lt;&lt;</span> endl<span style="color: #339933;">;</span> <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span><br />
class SubClass <span style="color: #339933;">:</span> public SuperClass <span style="color: #009900;">&#123;</span><br />
public<span style="color: #339933;">:</span><br />
&nbsp; &nbsp; <span style="color: #993333;">void</span> func<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> <a href="http://www.opengroup.org/onlinepubs/009695399/functions/cout.html"><span style="color: #000066;">cout</span></a> <span style="color: #339933;">&lt;&lt;</span> <span style="color: #ff0000;">&quot;SubClass::func()&quot;</span> <span style="color: #339933;">&lt;&lt;</span> endl<span style="color: #339933;">;</span> <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span><br />
<span style="color: #993333;">int</span> main<span style="color: #009900;">&#40;</span><span style="color: #993333;">int</span> argc<span style="color: #339933;">,</span> <span style="color: #993333;">char</span> <span style="color: #339933;">**</span>argv <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp;SubClass sub<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp;SuperClass <span style="color: #339933;">*</span>super <span style="color: #339933;">=&amp;</span>sub<span style="color: #339933;">;</span> <br />
&nbsp; &nbsp; &nbsp;super<span style="color: #339933;">-&gt;</span>func<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp;<span style="color: #b1b100;">return</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span></div></div>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">[実行結果]<br />
SuperClass::func()</div></div>
<p><h2>VIRTUAL FUNCTION, VTABLE, and VPOINTER</h2>
<p>次にVirtual関数の例を説明する。さきほどの例ではUPCASTによりSubClassクラスではなくSuperClassクラスのfunc関数がcallされた。ここではSuperClassの関数にvirtualをつけた場合のfunc関数の振る舞いを確かめてみる。virtual関数func1、func2をもつSuperClassを継承した3つのSubClassを用意する。これら3つはそれぞれfunc1、func2両方とも、func1のみ、func2のみをoverrideしている。 実行結果はSubClassでvirtual関数をoverrideした場合はその内容が、そうでない場合はSuperClassの内容が表示される。</p>
<div class="codecolorer-container c default" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;"><div class="c codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #339933;">#include &lt;iostream&gt;</span><br />
using std<span style="color: #339933;">::</span><a href="http://www.opengroup.org/onlinepubs/009695399/functions/cout.html"><span style="color: #000066;">cout</span></a><span style="color: #339933;">;</span><br />
using std<span style="color: #339933;">::</span><span style="color: #202020;">endl</span><span style="color: #339933;">;</span><br />
class SuperClass <span style="color: #009900;">&#123;</span><br />
public<span style="color: #339933;">:</span><br />
&nbsp; &nbsp; virtual <span style="color: #993333;">void</span> funcA<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> <a href="http://www.opengroup.org/onlinepubs/009695399/functions/cout.html"><span style="color: #000066;">cout</span></a> <span style="color: #339933;">&lt;&lt;</span> <span style="color: #ff0000;">&quot;SuperClass::funcA()&quot;</span> <span style="color: #339933;">&lt;&lt;</span> endl<span style="color: #339933;">;</span> <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; virtual <span style="color: #993333;">void</span> funcB<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> <a href="http://www.opengroup.org/onlinepubs/009695399/functions/cout.html"><span style="color: #000066;">cout</span></a> <span style="color: #339933;">&lt;&lt;</span> <span style="color: #ff0000;">&quot;SuperClass::funcB()&quot;</span> <span style="color: #339933;">&lt;&lt;</span> endl<span style="color: #339933;">;</span> <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span><br />
class SubClass1 <span style="color: #339933;">:</span> public SuperClass <span style="color: #009900;">&#123;</span><br />
public<span style="color: #339933;">:</span><br />
&nbsp; &nbsp; <span style="color: #993333;">void</span> funcA<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> <a href="http://www.opengroup.org/onlinepubs/009695399/functions/cout.html"><span style="color: #000066;">cout</span></a> <span style="color: #339933;">&lt;&lt;</span> <span style="color: #ff0000;">&quot;SubClass1::funcA()&quot;</span> <span style="color: #339933;">&lt;&lt;</span> endl<span style="color: #339933;">;</span> <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #993333;">void</span> funcB<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> <a href="http://www.opengroup.org/onlinepubs/009695399/functions/cout.html"><span style="color: #000066;">cout</span></a> <span style="color: #339933;">&lt;&lt;</span> <span style="color: #ff0000;">&quot;SubClass1::funcB()&quot;</span> <span style="color: #339933;">&lt;&lt;</span> endl<span style="color: #339933;">;</span> <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span><br />
class SubClass2 <span style="color: #339933;">:</span> public SuperClass <span style="color: #009900;">&#123;</span><br />
public<span style="color: #339933;">:</span><br />
&nbsp; &nbsp; <span style="color: #993333;">void</span> funcA<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> <a href="http://www.opengroup.org/onlinepubs/009695399/functions/cout.html"><span style="color: #000066;">cout</span></a> <span style="color: #339933;">&lt;&lt;</span> <span style="color: #ff0000;">&quot;SubClass2::funcA()&quot;</span> <span style="color: #339933;">&lt;&lt;</span> endl<span style="color: #339933;">;</span> <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span><br />
class SubClass3 <span style="color: #339933;">:</span> public SuperClass <span style="color: #009900;">&#123;</span><br />
public<span style="color: #339933;">:</span><br />
&nbsp; &nbsp; <span style="color: #993333;">void</span> funcB<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> <a href="http://www.opengroup.org/onlinepubs/009695399/functions/cout.html"><span style="color: #000066;">cout</span></a> <span style="color: #339933;">&lt;&lt;</span> <span style="color: #ff0000;">&quot;SubClass2::funcB()&quot;</span> <span style="color: #339933;">&lt;&lt;</span> endl<span style="color: #339933;">;</span> <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span><br />
<span style="color: #993333;">int</span> main<span style="color: #009900;">&#40;</span><span style="color: #993333;">int</span> argc<span style="color: #339933;">,</span> <span style="color: #993333;">char</span> <span style="color: #339933;">**</span>argv <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; SubClass1 sub1<span style="color: #339933;">;</span> SubClass2 sub2<span style="color: #339933;">;</span> SubClass3 sub3<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <a href="http://www.opengroup.org/onlinepubs/009695399/functions/cout.html"><span style="color: #000066;">cout</span></a> <span style="color: #339933;">&lt;&lt;</span> &nbsp;<span style="color: #ff0000;">&quot;***************SubClass1***************&quot;</span> <span style="color: #339933;">&lt;&lt;</span> &nbsp;endl<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; SuperClass <span style="color: #339933;">*</span>super <span style="color: #339933;">=&amp;</span>sub1<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; super<span style="color: #339933;">-&gt;</span>funcA<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> super<span style="color: #339933;">-&gt;</span>funcB<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <a href="http://www.opengroup.org/onlinepubs/009695399/functions/cout.html"><span style="color: #000066;">cout</span></a> <span style="color: #339933;">&lt;&lt;</span> <span style="color: #ff0000;">&quot;***************SubClass2***************&quot;</span> <span style="color: #339933;">&lt;&lt;</span> endl<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; super <span style="color: #339933;">=&amp;</span>sub2<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; super<span style="color: #339933;">-&gt;</span>funcA<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> super<span style="color: #339933;">-&gt;</span>funcB<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <a href="http://www.opengroup.org/onlinepubs/009695399/functions/cout.html"><span style="color: #000066;">cout</span></a> <span style="color: #339933;">&lt;&lt;</span> <span style="color: #ff0000;">&quot;***************SubClass3***************&quot;</span> <span style="color: #339933;">&lt;&lt;</span> endl<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; super <span style="color: #339933;">=&amp;</span>sub3<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; super<span style="color: #339933;">-&gt;</span>funcA<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>super<span style="color: #339933;">-&gt;</span>funcB<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">return</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span></div></div>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">[実行結果]<br />
***************SubClass1***************<br />
SubClass1::funcA()<br />
SubClass1::funcB()<br />
***************SubClass2***************<br />
SubClass2::funcA()<br />
SuperClass::funcB()<br />
***************SubClass3***************<br />
SuperClass::funcA()<br />
SubClass2::funcB()</div></div>
<p>virtualな関数の場合はコンパイラは型ではなくてオブジェクトのポインタを見ていて実行時にどのfuncが実行されるべきかを判断する。非virtual関数の時と違いコンパイラーはコンパイル時にはどのfuncが呼ばれるのか判別できない。この実行時にどのfuncが呼ばれるのか決定することを<a href="http://en.wikipedia.org/wiki/Dynamic_binding_%28computer_science%29">Dynamic Binding</a>と呼ぶ。そしてこのDynamic Bindingは<a href="http://en.wikipedia.org/wiki/Virtual_method_table">Virtual Function table(Vtable)</a>と呼ばれるメカニズムによって実現される。ようやく本題。</p>
<p>Vtableとはvirtual関数を持っているクラスや親クラスで定義されているvirtual関数をoverrideしたクラスに対してコンパイラーが作成する（その名のとおり）仮想テーブルである。コンパイラーはvirtual関数を持っている/virtaul関数をoverrideしているクラスにのみクラスごとのVtableを作成してその中にbindすべき関数ポインターを持っている。<br />
またこのVtableを指すポインタのことをvpointerと呼ぶ。コンパイラはVtableを持っているクラスに対してvpointerを隠しメンバー変数として追加する。さらにコンストラクタにそのvpointer変数の初期化を行うコードを追加する。よってオブジェクトが作成されるとき隠しメンバー変数vpointerは対応するVtableアドレスで初期化され、実行時の実行関数の決定は内部でvpointerを通じてVtableをlookupすることで実現される。　（参照: <a href="http://en.wikipedia.org/wiki/Virtual_method_table#Implementation">wikipedia:vtable implementation</a>）</p>
<p>Vtableに作成される関数ポインターは、そのクラスで持っているvirtual関数のポインター、親クラスで定義されているvirtaul関数をoverrideした関数のポインター、また親クラスでvirtual定義されている関数をoverrideしない場合はその親のvirtual関数ポインタが含まれることになる。上記サンプルにあるSuperClass, SubClass[1-3]に対するオブジェクトとvpointer、vtableとそのvtableに含まれる関数ポインターの関係を図にすると以下のようになる。</p>
<p style="text-align: center;">
<a href="http://www.flickr.com/photos/yk55/4391268309/" title="vtable - Virtual Function Table by yoichi*, on Flickr"><img src="http://farm3.static.flickr.com/2686/4391268309_604635db6c_o.png" width="589" height="467" alt="vtable - Virtual Function Table" /></a>
</p>
<p>上図を元にサンプル中のSubClass1::funcAのDynamic Bindingイメージを式化してみると次のような感じになる・ vptr1はSubClass1のvpointerとする。 あくまでイメージであり(vptr->)は実際は見えません。</p>
<div class="codecolorer-container c default" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;"><div class="c codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">SubClass1 sub1<span style="color: #339933;">;</span><br />
SuperClass <span style="color: #339933;">*</span>super <span style="color: #339933;">=&amp;</span>sub1<span style="color: #339933;">;</span><br />
super<span style="color: #339933;">-&gt;</span>vptr<span style="color: #339933;">-&gt;</span>funcA<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> &nbsp; &nbsp;<span style="color: #666666; font-style: italic;">// SubClass1::funcA(),</span></div></div>
<p><h2>g++ -fdump-class-hierarchのダンプ結果</h2>
<p>最後にg++の-fdump-class-hierarchオプションによるVtableのダンプ結果を見てみる。上記サンプルファイルをvtable.cppとして次のようにコンパイルを行う。　（参考: <a href="http://gcc.gnu.org/onlinedocs/gcc-4.4.3/gcc/Debugging-Options.html#Debugging-Options">Options for Debugging Your Program or GCC</a>）</p>
<pre>
 g++ -fdump-class-hierarchy vtable.cc -o vtable
</pre>
<p>これでコンパイルが終わりvtable実行ファイルができあがる。また同一ディレクトリにvtable.cpp.002t.classという名前のファイルが出来上がる。このファイルにVtableのダンプ結果が出力されている。各クラスのVtable中を見るといまいち意味のわからないものはあるが上図のとおりの関数が含まれており、また各クラスにはvptrを見つけることができる。</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">Vtable for SubClass1<br />
SubClass1::_ZTV9SubClass1: 4u entries<br />
0 &nbsp; &nbsp; (int (*)(...))0<br />
4 &nbsp; &nbsp; (int (*)(...))(&amp; _ZTI9SubClass1)<br />
8 &nbsp; &nbsp; SubClass1::funcA<br />
12 &nbsp; &nbsp;SubClass1::funcB<br />
<br />
Class SubClass1<br />
&nbsp; &nbsp;size=4 align=4<br />
&nbsp; &nbsp;base size=4 base align=4<br />
SubClass1 (0xb7254a80) 0 nearly-empty<br />
&nbsp; &nbsp; vptr=((&amp; SubClass1::_ZTV9SubClass1) + 8u)<br />
&nbsp; SuperClass (0xb707c1e0) 0 nearly-empty<br />
&nbsp; &nbsp; &nbsp; primary-for SubClass1 (0xb7254a80)<br />
<br />
Vtable for SubClass2<br />
SubClass2::_ZTV9SubClass2: 4u entries<br />
0 &nbsp; &nbsp; (int (*)(...))0<br />
4 &nbsp; &nbsp; (int (*)(...))(&amp; _ZTI9SubClass2)<br />
8 &nbsp; &nbsp; SubClass2::funcA<br />
12 &nbsp; &nbsp;SuperClass::funcB<br />
<br />
Class SubClass2<br />
&nbsp; &nbsp;size=4 align=4<br />
&nbsp; &nbsp;base size=4 base align=4<br />
SubClass2 (0xb7254b80) 0 nearly-empty<br />
&nbsp; &nbsp; vptr=((&amp; SubClass2::_ZTV9SubClass2) + 8u)<br />
&nbsp; SuperClass (0xb707c3c0) 0 nearly-empty<br />
&nbsp; &nbsp; &nbsp; primary-for SubClass2 (0xb7254b80)<br />
<br />
Vtable for SubClass3<br />
SubClass3::_ZTV9SubClass3: 4u entries<br />
0 &nbsp; &nbsp; (int (*)(...))0<br />
4 &nbsp; &nbsp; (int (*)(...))(&amp; _ZTI9SubClass3)<br />
8 &nbsp; &nbsp; SuperClass::funcA<br />
12 &nbsp; &nbsp;SubClass3::funcB<br />
<br />
Class SubClass3<br />
&nbsp; &nbsp;size=4 align=4<br />
&nbsp; &nbsp;base size=4 base align=4<br />
SubClass3 (0xb7254c40) 0 nearly-empty<br />
&nbsp; &nbsp; vptr=((&amp; SubClass3::_ZTV9SubClass3) + 8u)<br />
&nbsp; SuperClass (0xb707c528) 0 nearly-empty<br />
&nbsp; &nbsp; &nbsp; primary-for SubClass3 (0xb7254c40)</div></div>
<p>おわり</p>
]]></content:encoded>
			<wfw:commentRss>http://yk55.com/blog/2010/02/27/dynamic-binding-vtable-concept/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>C++ :: typeidとdemangleで実行時クラス名取得</title>
		<link>http://yk55.com/blog/2010/01/20/get_cpp_classname_by_typeid_and_demangle/</link>
		<comments>http://yk55.com/blog/2010/01/20/get_cpp_classname_by_typeid_and_demangle/#comments</comments>
		<pubDate>Tue, 19 Jan 2010 20:27:20 +0000</pubDate>
		<dc:creator>yoichi</dc:creator>
				<category><![CDATA[Programming / プログラミング]]></category>
		<category><![CDATA[cplusplus]]></category>
		<category><![CDATA[gcc]]></category>
		<category><![CDATA[rtti]]></category>

		<guid isPermaLink="false">http://yk55.com/blog/?p=59</guid>
		<description><![CDATA[Javaでは普通に行われている実行時の型情報取得（ Object.getClass(), Class.getName()とかinstanceOfとかね ）ですが、CではできないのだからどうせC++でもできないのだろうなと思っていたら予想に反しRunＴime Type Identification (RTTI)という実行時の型情報取得機能がばっちり用意されてました。 確かにdynamic_castができているわけだし、まあそういうことだよねと納得。 ということでC++で実行時クラス名の取得を試みました。
実行時型情報取得はtypeid演算子を使います。typeid演算子はtype_info型クラスの参照を返し、そのtype_infoのメンバname()より型情報の文字列が取得できます。 それでは次のコードで型情報を取得してみます。
#include &#60;iostream&#62;
#include &#60;typeinfo&#62;
using std::cout;
using std::endl;
using std::type_info;

class Parent&#123;
public:
&#160; virtual void x&#40;&#41;&#123;&#125;
&#125;;
class Child : public Parent &#123;&#125;;

main&#40;&#41;&#123;
&#160; &#160; Parent* p;
&#160; &#160; p = new Parent&#40;&#41;;
&#160; &#160; const type_info &#38; id_p = typeid&#40;*p&#41;;
&#160; &#160; cout &#60;&#60; id_p.name&#40;&#41; &#60;&#60; endl;
&#160; &#160; p = new Child&#40;&#41;;
&#160; &#160; const type_info &#38; id_c [...]]]></description>
			<content:encoded><![CDATA[<p>Javaでは普通に行われている実行時の型情報取得（ Object.getClass(), Class.getName()とかinstanceOfとかね ）ですが、CではできないのだからどうせC++でもできないのだろうなと思っていたら予想に反し<a href="http://en.wikipedia.org/wiki/Run-time_type_information">RunＴime Type Identification (RTTI)</a>という実行時の型情報取得機能がばっちり用意されてました。 確かにdynamic_castができているわけだし、まあそういうことだよねと納得。 ということでC++で実行時クラス名の取得を試みました。</p>
<p>実行時型情報取得は<a href="http://en.wikipedia.org/wiki/Typeid">typeid</a>演算子を使います。typeid演算子は<a href="http://www.cplusplus.com/reference/std/typeinfo/type_info/">type_info</a>型クラスの参照を返し、そのtype_infoのメンバname()より型情報の文字列が取得できます。 それでは次のコードで型情報を取得してみます。</p>
<div class="codecolorer-container cpp default" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;"><div class="cpp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #339900;">#include &lt;iostream&gt;</span><br />
<span style="color: #339900;">#include &lt;typeinfo&gt;</span><br />
<span style="color: #0000ff;">using</span> std<span style="color: #008080;">::</span><span style="color: #0000dd;">cout</span><span style="color: #008080;">;</span><br />
<span style="color: #0000ff;">using</span> std<span style="color: #008080;">::</span><span style="color: #007788;">endl</span><span style="color: #008080;">;</span><br />
<span style="color: #0000ff;">using</span> std<span style="color: #008080;">::</span><span style="color: #007788;">type_info</span><span style="color: #008080;">;</span><br />
<br />
<span style="color: #0000ff;">class</span> Parent<span style="color: #008000;">&#123;</span><br />
<span style="color: #0000ff;">public</span><span style="color: #008080;">:</span><br />
&nbsp; <span style="color: #0000ff;">virtual</span> <span style="color: #0000ff;">void</span> x<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span><br />
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span><br />
<span style="color: #0000ff;">class</span> Child <span style="color: #008080;">:</span> <span style="color: #0000ff;">public</span> Parent <span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span><br />
<br />
main<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#123;</span><br />
&nbsp; &nbsp; Parent<span style="color: #000040;">*</span> p<span style="color: #008080;">;</span><br />
&nbsp; &nbsp; p <span style="color: #000080;">=</span> <span style="color: #0000dd;">new</span> Parent<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">const</span> type_info <span style="color: #000040;">&amp;</span> id_p <span style="color: #000080;">=</span> <span style="color: #0000ff;">typeid</span><span style="color: #008000;">&#40;</span><span style="color: #000040;">*</span>p<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; <span style="color: #0000dd;">cout</span> <span style="color: #000080;">&lt;&lt;</span> id_p.<span style="color: #007788;">name</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #000080;">&lt;&lt;</span> endl<span style="color: #008080;">;</span><br />
&nbsp; &nbsp; p <span style="color: #000080;">=</span> <span style="color: #0000dd;">new</span> Child<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">const</span> type_info <span style="color: #000040;">&amp;</span> id_c <span style="color: #000080;">=</span> <span style="color: #0000ff;">typeid</span><span style="color: #008000;">&#40;</span><span style="color: #000040;">*</span>p<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; <span style="color: #0000dd;">cout</span> <span style="color: #000080;">&lt;&lt;</span> id_c.<span style="color: #007788;">name</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #000080;">&lt;&lt;</span> endl<span style="color: #008080;">;</span><br />
<span style="color: #008000;">&#125;</span></div></div>
<p>これをコンパイル(gcc 4.3.2)後に実行した結果は次のとおり。</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">6Parent<br />
5Child</div></div>
<p>ParentクラスとChildクラスそれぞれの結果は確かにそれっぽいものが得られましたがなぜかクラス名の前に文字数がくっついてます。 どうしたもんだと思ってググってみるとまさに<a href="http://ml.tietew.jp/cppll/cppll/thread_articles/8646">ピンポイントなMLでの議論</a>を発見。 クラスの前の数字がゴミに見えて気づかなかったのですがこれは<a href="http://en.wikipedia.org/wiki/Name_mangling">マングリング</a>された文字列でした。 というわけで問題はデマングリングで解決します。上記MLではその法についても紹介されていたのでそれを参考にデマングリングを試みます。</p>
<p>デマングリングにはcxxabi.hに定義されている__cxa_demangle()関数を使用します。まずはヘッダを覗いてみます。</p>
<p><u>__cxa_demangle() @ /usr/include/c++/4.1.3/cxxabi.h</u></p>
<div class="codecolorer-container cpp default" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;"><div class="cpp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #339900;">#ifdef __cplusplus</span><br />
<span style="color: #0000ff;">namespace</span> __cxxabiv1<br />
<span style="color: #008000;">&#123;</span><br />
&nbsp; <span style="color: #0000ff;">extern</span> <span style="color: #FF0000;">&quot;C&quot;</span><br />
&nbsp; <span style="color: #008000;">&#123;</span><br />
<span style="color: #339900;">#endif</span><br />
...略...<br />
&nbsp; <span style="color: #666666;">// Demangling routines.</span><br />
&nbsp; <span style="color: #0000ff;">char</span><span style="color: #000040;">*</span><br />
&nbsp; __cxa_demangle<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> <span style="color: #0000ff;">char</span><span style="color: #000040;">*</span> __mangled_name, <span style="color: #0000ff;">char</span><span style="color: #000040;">*</span> __output_buffer,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #0000ff;">size_t</span><span style="color: #000040;">*</span> __length, <span style="color: #0000ff;">int</span><span style="color: #000040;">*</span> __status<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
<span style="color: #339900;">#ifdef __cplusplus</span><br />
&nbsp; <span style="color: #008000;">&#125;</span><br />
<span style="color: #008000;">&#125;</span> <span style="color: #666666;">// namespace __cxxabiv1</span><br />
<span style="color: #339900;">#endif</span><br />
...略...<br />
<span style="color: #666666;">// User programs should use the alias `abi'.</span><br />
<span style="color: #0000ff;">namespace</span> abi <span style="color: #000080;">=</span> __cxxabiv1<span style="color: #008080;">;</span></div></div>
<p>次にこの__cxa_demangle()を使って先のマングルされた文字列をデマングルしてみます。</p>
<div class="codecolorer-container cpp default" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;"><div class="cpp codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #339900;">#include &lt;iostream&gt;</span><br />
<span style="color: #339900;">#include &lt;typeinfo&gt;</span><br />
<span style="color: #339900;">#include &lt;cxxabi.h&gt;</span><br />
<span style="color: #0000ff;">using</span> std<span style="color: #008080;">::</span><span style="color: #0000dd;">cout</span><span style="color: #008080;">;</span><br />
<span style="color: #0000ff;">using</span> std<span style="color: #008080;">::</span><span style="color: #007788;">endl</span><span style="color: #008080;">;</span><br />
<span style="color: #0000ff;">using</span> std<span style="color: #008080;">::</span><span style="color: #007788;">type_info</span><span style="color: #008080;">;</span><br />
<br />
<span style="color: #0000ff;">class</span> Parent<span style="color: #008000;">&#123;</span><br />
<span style="color: #0000ff;">public</span><span style="color: #008080;">:</span><br />
&nbsp; <span style="color: #0000ff;">virtual</span> <span style="color: #0000ff;">void</span> x<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span> &nbsp;<span style="color: #666666;">// 1. 仮想メソッド宣言</span><br />
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span><br />
<span style="color: #0000ff;">class</span> Child <span style="color: #008080;">:</span> <span style="color: #0000ff;">public</span> Parent <span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span><br />
<br />
main<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#123;</span><br />
&nbsp; &nbsp; Parent<span style="color: #000040;">*</span> p<span style="color: #008080;">;</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">int</span> status<span style="color: #008080;">;</span><br />
&nbsp; &nbsp; p <span style="color: #000080;">=</span> <span style="color: #0000dd;">new</span> Parent<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">const</span> type_info <span style="color: #000040;">&amp;</span> id_p <span style="color: #000080;">=</span> <span style="color: #0000ff;">typeid</span><span style="color: #008000;">&#40;</span><span style="color: #000040;">*</span>p<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; <span style="color: #0000dd;">cout</span> <span style="color: #000080;">&lt;&lt;</span> abi<span style="color: #008080;">::</span>__cxa_demangle<span style="color: #008000;">&#40;</span>id_p.<span style="color: #007788;">name</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>, 0, 0, <span style="color: #000040;">&amp;</span>status<span style="color: #008000;">&#41;</span> <span style="color: #000080;">&lt;&lt;</span> endl<span style="color: #008080;">;</span><br />
&nbsp; &nbsp; p <span style="color: #000080;">=</span> <span style="color: #0000dd;">new</span> Child<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">const</span> type_info <span style="color: #000040;">&amp;</span> id_c <span style="color: #000080;">=</span> <span style="color: #0000ff;">typeid</span><span style="color: #008000;">&#40;</span><span style="color: #000040;">*</span>p<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><br />
&nbsp; &nbsp; <span style="color: #0000dd;">cout</span> <span style="color: #000080;">&lt;&lt;</span> abi<span style="color: #008080;">::</span>__cxa_demangle<span style="color: #008000;">&#40;</span>id_c.<span style="color: #007788;">name</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>, 0, 0, <span style="color: #000040;">&amp;</span>status<span style="color: #008000;">&#41;</span> <span style="color: #000080;">&lt;&lt;</span> endl<span style="color: #008080;">;</span><br />
<span style="color: #008000;">&#125;</span></div></div>
<p>デマングル版コードをコンパイル(gcc 4.3.2)後に実行してみると無事クラス名が出力。 ということで見事実行時クラス名の取得に成功しました。</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">Parent<br />
Child</div></div>
<p>おわり</p>
]]></content:encoded>
			<wfw:commentRss>http://yk55.com/blog/2010/01/20/get_cpp_classname_by_typeid_and_demangle/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
