型の名前

C++には、typeid演算子という実行時に型情報を取得することが出来る演算子が存在する。

typeid演算子const std::type_info&を返す。また、std::type_info::nameで実行時定義の型名を取り出すことが出来る。なお、gcc4.10.0及びclang3.5.0の時点ではマングリングされた名前を返す。

 

実際の挙動

実際に実行し、type_infoの挙動を確かめてみた。

#include<iostream>

#include<typeinfo>

namespace nsA

{

class VirtualBase

{

public:

virtual void vfunc(){};

};

class Virtual : public VirtualBase

{

public:

virtual void vfunc() override {};

};

class NonVirtualBase{};

class NonVirtual : public NonVirtualBase{};

template<typename T>

class Template{};

struct Struct{};

namespace nsB

{

class Inner{};

}

}

int main()

{

int *p = new int(0);

std::cout << "Pointer : " << typeid(p).name() << std::endl

<< "Value : " << typeid(*p).name() << std::endl;

std::cout << std::endl;

nsA::VirtualBase *v;

nsA::NonVirtualBase *nv;

v = new nsA::VirtualBase();

nv = new nsA::NonVirtualBase();

std::cout << "class nsA::VirtualBase : " << typeid(*v).name() << std::endl

<< "class nsA::NonVirtualBase : " << typeid(*nv).name() << std::endl;

v = new nsA::Virtual();

nv = new nsA::NonVirtual();

std::cout << "class nsA::Virtual : " << typeid(*v).name() << std::endl

<< "class nsA::NonVirtual : " << typeid(*nv).name() << std::endl;

std::cout << std::endl;

nsA::Template<int> t;

nsA::Struct s;

nsA::nsB::Inner i;

std::cout << "class nsA::Template<int> : " << typeid(t).name() << std::endl

<< "class nsA::nsB::Inner : " << typeid(i).name() << std::endl

<< "struct nsA::Struct : " << typeid(s).name() << std::endl;

}

 

gcc4.10.0及びclang3.5.0の出力は同じで、以下のようになった。

Pointer : Pi

Value : i

class nsA::VirtualBase : N3nsA11VirtualBaseE

class nsA::NonVirtualBase : N3nsA14NonVirtualBaseE

class nsA::Virtual : N3nsA7VirtualE

class nsA::NonVirtual : N3nsA14NonVirtualBaseE

class nsA::Template<int> : N3nsA8TemplateIiEE

class nsA::nsB::Inner : N3nsA3nsB5InnerE

struct nsA::Struct : N3nsA6StructE

 

なお、Visual C++ 2013では以下のように完全な型名を返した。

Pointer : int *

Value : int

class nsA::VirtualBase : class nsA::VirtualBase

class nsA::NonVirtualBase : class nsA::NonVirtualBase

class nsA::Virtual : class nsA::Virtual

class nsA::NonVirtual : class nsA::NonVirtualBase

class nsA::Template<int> : class nsA::Template<int>

class nsA::nsB::Inner : class nsA::nsB::Inner

struct nsA::Struct : struct nsA::Struct

 

実際の型と違う

仮想関数を持たない型に注目すると、実態はNonVirtual型であるにも関わらず、NonVirtualBase型と同じ出力になっていることがわかる。

これは、一般的に実行時型情報が仮想関数テーブルに格納されることによるらしい(参考サイト1より)。

 

ところで

なんか今回気分的に文体が真面目だけど、NonVirtualとかいう名前をつけている辺り完全に実力不足なのが露呈してる。

 

参考にしたサイト