WisdomSoft - for your serial experiences.

基本型

C++/CLI では標準 C++ の基本型を .NET Framework の基本型として暗黙的に扱うため、意識することなく相互運用できます。例えば int 型の値は .NET Framework のコード内では System::Int32 構造体の値として扱われ、ネイティブ関数などで利用される場合は標準 C++ の単純な整数として扱われます。

C++基本型と .NET Frameworkの基本型

C++ 言語のキーワードで定められている基本型は、.NET Framework のライブラリにある構造体に関連付けられています。例えば int 型の変数は従来の C++ 言語であれば、通常は 32 ビットの整数型として利用することができましたが、マネージ型を利用する場合は System::Int32 構造体型の別名とされます。

表1 C++基本型に対応する .NET Frameworkの基本型
C++ 型 .NET Framework 型
bool System::Boolean
signed char System::SByte
unsigned char System::Byte
wchar_t System::Char
double、long double System::Double
float System::Single
int、signed int、long、signed long System::Int32
unsigned int、unsigned long System::UInt32
__int64、signed __int64 System::Int64
unsigned __int64 System::UInt64
short、signed short System::Int16
unsigned short System::UInt16
void System::Void

C++ 基本型に等価な .NET Framework 基本型の対応が表1です。.NET Framework の基本型は、全てが構造体型なので、従来の C/C++ 言語のように単純なデータサイズを表しているだけではなく、データを操作するためのメソッドなども同時に提供されています。全てのデータ型の詳細を説明することはできませんが、多くの構造体の操作方法は共通しています。また、普段は構造体 型であることを意識する必要は無いでしょう。

この場では System::Int32 構造体型に注目してみます。

System::Int32 構造体
System::Object 
    System::ValueType
        System::Int32
[SerializableAttribute] 
[ComVisibleAttribute(true)] 
public value class Int32 : IComparable, IFormattable, IConvertible, IComparable<int>, IEquatable<int>

これが、マネージ型の Int32 構造体の宣言です。従来の C++ の構文では見られない、属性を宣言する [ ] に括られた修飾子が見られますが、マネージ型の宣言方法については後ほど解説するので、この場ではこのような形でマネージ型の構造体が宣言されているものだと考えてください。

コード1
#include <cstdio>

int main()
{
	int i = 10;
	System::Int32 mi = 100;

	printf("mi + i = %d\n" , mi + i);

	return 0;
}
実行結果
コード1 実行結果

コード1では、int 型の変数 i と、System::Int32 型の変数 mi を宣言しています。これらの変数の型は異なる形ですが、int 型は表1を見ての通り Int32 構造体の別名に過ぎません。よって、i 変数と mi 変数は同一の型として等価に扱われます。また、このプログラムでは意図的に cout や WriteLine() ではなく、C 言語で使われていた printf() 関数に結果を渡していますが、この場合も問題はありません。Int32 型の値は、C++ の int 型として扱うことも可能です。

通常は、わざわざ Int32 であることを明記する必要はないので、これまで通り C++ の基本型で変数を宣言すると良いでしょう。

Int32 型は構造体なので、データ型に関連する操作を提供するメソッドが公開されています。この場では、指定した値がオブジェクトと同一かどうかを調べる Equals() メソッドに注目してみましょう。

System::Int32 構造体 Equals() メソッド
public:
virtual bool Equals (int obj) sealed

obj には、比較対象となる int 型の値を指定します。指定した値とオブジェクトの値が等しければ true、そうでなければ false が返ります。 上記の Equals() メソッドは Int32 のメソッドなので、数値型変数から直接呼び出すことができます。

コード2
int main()
{
	int i1 = 10;
	int i2 = 10;

	System::Console::WriteLine(i1.Equals(i2));
	System::Console::WriteLine(i1.Equals(100));

	return 0;
}
実行結果
コード2 実行結果

i1 変数と i2 変数は、それぞれ 10 という値で初期化されています。当然、i1.Equals(i2) は i1 と i2 変数の値が等しいため結果は true となります。しかし、i1.Equals(100) は、i1 に格納されている値 10 と 100 を比較するため、等しくならないので false という結果が得られます。

.NET Framework では、数値リテラルは Int32 構造体型として扱われます。これは、数値リテラルも単純なデータ型ではなく、オブジェクトとしてメソッドやプロパティを保有しているということを意味しています。 そのため、次のような記述が許されることになります。

(10).Equals(100)

上記の書き方は、10 という数値リテラルを Int32 型のオブジェクトとして扱うことができることを表しています。( ) で括られているのは、単純に 10.Equals(100) と書いてしまった場合は . 記号によって浮動小数点リテラルであると解釈されてしまうためです。同様に、bool 型のリテラル true や false や、文字リテラル 'A' なども単純なデータではなく System::Boolean 構造体や Systen::SByte 構造体のオブジェクトとして扱うことができます。

コード3
int main()
{
	System::Console::WriteLine('A'.GetType());
	System::Console::WriteLine(L'B'.GetType());
	System::Console::WriteLine((10).GetType());
	System::Console::WriteLine((.1F).GetType());
	System::Console::WriteLine((.1).GetType());
	System::Console::WriteLine(true.GetType());

	return 0;
}
実行結果
コード3 実行結果

コード3は、リテラルから直接オブジェクトのメソッドを呼び出しているプログラムの例です。このプログラムで呼び出している GetType() メソッドは、対象オブジェクトの型情報を格納する System::Type クラスのオブジェクトを返します。Type クラスの詳細については割愛しますが、このオブジェクトを取得することによって、実行結果のように実行時にオブジェクトの型情報を取得することができます。

C++ 言語の文字リテラルの扱い方は、シングルバイト文字か、ワイド文字によって異なります。単純な文字リテラルは System::SByte 型のオブジェクトとして扱われますが、L 接頭辞を指定したワイド文字の場合は System::Char 構造体型として扱われます。.NET Framework では、アプリケーションの国際化を容易にするために、文字や文字列型のオブジェクトは全て Unicode を利用します。よって、wchar_t 型の値が文字列を表す Char クラス型のオブジェクトとして扱われるのです。