C++Builder 2009 ファーストガイド 第七回「C++基礎知識(後編)」

By: Tomohiro Takahashi

Abstract: C++基礎知識(後編)の説明です。

このファーストガイドは、これからC++Builder 2009を使い始める初心者の方を対象に10回に分けて基本的事項を説明していきます。

第七回は、C++基礎知識の後編としまして、C/C++言語を使ってプログラミングする上で必要不可欠である「データ」を中心に説明していきます。また、後半ではC++Builder特有の型についても紹介します。

    データ型

以下、標準の組み込みデータ型を説明するとともに、独自に新しいデータ型を作成する方法を説明します。

    数値型

順序数値型は整数型であり、いろいろな整数型が用意されています。 整数型は、常に(小数部を持たない)自然数です。

    数値型, 整数型

範囲

内部形式

short

-32768 .. 32767

符号付き 16 ビット

intlong

-2147483648 .. 2147483647

符号付き 32 ビット

    浮動小数点型

範囲

サイズ

dloat

3.4*(10**-38) 3.4*(10**+38)

4 バイト

double

5.0*10E-324 .. 1.7*10E308

8 バイト

long double

3.410E-4932 .. 1.1*10E4932

80 ビット

    文字型

C++ の文字型は、その名前のとおりに単独の文字を格納する型です。文字型は、任意のASCII文字を保持できます。文字データ型を定義するには、型指定子 char を使います。char型の変数は 1 バイトの長さを持ちます。

charには、符号付きchar、符号なしchar、または指定なしcharがあります。デフォルトでは signed char が想定されます。文字(char)として宣言されたオブジェクトは、基本 ASCII文字セットの任意のメンバーを格納できる大きさを持ちます。

変換先

方法

char

int

ゼロまたは符号拡張(char 型のデフォルトによる)

unsigned char

int

常に上位バイトをゼロで埋める

signed char

int

常に符号拡張

short int

int

同じ値 符号拡張

unsigned short

unsigned int

同じ値 ゼロで埋める

enum

int

じ値

    論理型

論理型は、true または false の値しか取らない変数です。true と false はどちらも C++ の組み込み定数識別子なので(Cのように)定義する必要はなく、特殊な表記が必要になることもありません。

    ポインタ型

ポインタは、オブジェクトへのポインタと関数へのポインタの2種類に大別されます。両者ともに、メモリアドレスを持つ特殊なオブジェクトです。

この2つのポインタクラスは別々の属性、目的、処理規則を持ちますが、C++Builderの特定の操作においては共用されます。一般的には、関数へのポインタは、関数にアクセスするためと、関数を引数としてほかの関数に渡すために使われます。関数へのポインタに対して演算を行うことは認められていません。一方、オブジェクトへのポインタは、配列やメモリ上のより複雑なデータ構造をスキャンする際に、規則的にインクリメントおよびデクリメントされます。

    enum型

C++ では、enumを使って独自に型を作成することが可能です。

/* ユニークな整数型 enum days と、この型の変数 anyday
   および定数整数値を持つ1組の列挙子(sun, mon,...)を定義する。*/
enum days { sun, mon, tues, wed, thur, fri, sat } anyday;

/*
   "modes" は型タグ。
   "LASTMODE", "BW40", "C40", などは定数名。
   C40 の値は (BW40 + 1) で 1、 BW80 は (C40 + 1) で 2、...
*/
enum modes { LASTMODE = -1, BW40=0, C40, BW80, C80, MONO = 7 };

    データ構造

これまでは、C++ に用意されている基本的なデータ型を見てきました。以降では、単純型を集合体またはデータ構造にグループ化する方法を説明します。では、配列、構造体などを使って、関連するデータ型をグループ化する方法を見てみましょう。

    配列型

データ構造の中で最も単純なのが配列型です。配列を使うと、1つの変数に複数の値をリストとして格納できます。C++ では配列は常に型付きです。すなわち、配列要素はすべて同じ型でなければなりません。配列型を宣言するための一般的な構文を次に示します。

type declarator [定数式>]

配列を宣言する例を次に示します。

int MyArray[10]; // 11 個の int を格納する配列

long double **data;
data = new long double*[m];       // ステップ 1: 行を設定
for (int j = 0; j < m; j++) {
  data[j] = new long double[n];   // ステップ 2: 列を設定
}

最後の宣言では二次元配列を作成しています。また、配列の要素を参照する方法もここに示されています。C++ では配列は 0 をベースにします。すなわち、配列の最初の要素は位置 0 を持ちます。上記のMyArray整数配列内の最初の整数にアクセスするには、MyArray[0] と記述します。

配列には任意の型の変数を格納することができます。ただし、C++ では1つの配列に対して同じ型を持つ変数しか格納できません。したがって、バリアント型の配列を作成しない限り、整数と文字列の両方を 1 つの配列に格納することはできません。それぞれの配列は、要素に許される型を持ちます。

    動的配列型

動的配列とは、サイズが固定されていない配列です。動的配列のメモリは、必要に応じてプログラマが明示的に割り当てます。

動的配列は、配列として実装されたサイズ変更が可能なコレクションです。C++Builderでは、動的配列の実装として動的配列DynamicArrayテンプレートが提供されます。動的配列DynamicArrayテンプレートは、Delphiの動的配列実装と互換性のあるバイナリレイアウトを使用しています。これにより、Pascalコードを使う Delphi と C++コードを使う C++Builder の間で互換性のある動的配列を共有できます。

動的配列の構文を次に示します。

template <class T> class DELPHIRETURN DynamicArray;

動的配列を宣言する例を次に示します。

DynamicArray<int> arrayOfInt;

arrayOfInt.Length = 10;
cout << "ArrayLength: " << arrayOfInt.Length << endl;

動的配列を解放するには、Length に 0 を指定します。

    構造体型

構造体型を使うと、複数の異なる型のメンバー変数を持つグループを定義し、論理的に同じメンバー名を持つグループの変数を複数個宣言してデータを格納できます。たとえば、 氏名、電話番号、および身長を1つの識別子で格納する顧客構造体を作成できます。構造体に関連付けられているそれぞれのデータメンバー変数は、「フィールドメンバー変数」と呼ばれます。

構造体を作成するための基本構文を以下に示します。

struct [<構造体型名>] {

  [<型> <変数名[, 変数名, ...]>] ;
    .
    .
    .

} [<構造体変数>] ;

構造体には、任意の型のフィールドを必要な数だけ指定できます。同じ型のフィールドが複数ある場合は、それらをカンマで区切って同じ型識別子を使うことができます。

顧客構造体の例を以下に示します。

#include <string.h>

struct my_struct {
  char name[80], phone_number[80];
  int  age, height;
} my_friend;

void func() {
   strcpy(my_friend.name, "Mr. Wizard");   /* 要素にアクセス */
}

struct my_struct my_friends[100];         /* 追加の変数を宣言 */

構造体内の要素にアクセスするには、メンバー選択子(.)または -> を使います。

同じ型を持つ追加の変数を宣言するには、キーワード struct に続けて <構造体型名> と変数名を順に記述します。C++ では変数を宣言する際に、キーワード struct を省略することができます。

    クラスとオブジェクト

オブジェクト指向言語C++では、クラスとオブジェクトとを区別する必要があります。クラスはオブジェクトの型を定義したもので、オブジェクトはクラスを物理的に表現したものです。この関係は、車の設計図と本物の車の関係にたとえることができます。クラスは設計図であり、本物の車はオブジェクトです。1つの車の設計図から、車をいくつでも作ることができます。

プログラミング用語では、クラスを定義することは型を定義することを意味します。その型のインスタンスを作成するには、オブジェクトを作成します。クラス定義は常に型であり、オブジェクト宣言は常に変数です。すなわち、オブジェクトは常に、プログラムまたはサブルーチンで宣言された実際の変数です。

クラスを宣言するための一般的な構文を以下に示します。

class TMyClass
{    
   <変数の型> <メンバー変数>;
   <変数の型> <メンバー変数>;

    TMyClass();   // コンストラクタ
    ~TMyClass();  // デストラクタ
    <メソッド名>;
};  //  TMyClass の宣言を閉じる

このクラスのオブジェクトを作成するための構文は以下のとおりです。

TMyClass* MyObj = new TMyClass();

    C++Builder特有のクラス・型

C++Builder では、予めたくさんのクラスが定義されています。その一部は特定のデータベース型(たとえばテーブルの通貨型と互換性のある Currency)に対応し、また別のクラスは利便性やVCLとの互換性のために定義されています。

    拡張整数型 __int8, __int16, __int32, __int64, unsigned __int64

C++Builderには拡張整数型が用意されており、64ビットの大きさの整数を扱える型もあります。なお、この拡張整数型を使うときには、適切なサフィクスを使用しなければなりません。

サフィックス

サイズ

__int8

i8

__int8 c = 127i8;

8 ビット

__int16

i16

__int16 s = 32767i16;

16 ビット

__int32

i32

__int32 i = 123456789i32;

32 ビット

__int64

i64

__int64 big = 12345654321i64;

64 ビット

unsigned __int64

ui64

unsigned __int64 hugeInt = 1234567887654321ui64;

64 ビット

    通貨クラス(Currency)

通貨クラス(Currency)は、通貨値を保持するために特別に設計された特殊な浮動小数点型を実装します。利用可能な通貨値の範囲は、-922,337,203,685,477.5808 ~ 922,337,203,685,477.5807 です。通貨型を扱う場合は、通貨クラスに定義されている演算子だけを使う必要があります。

    集合型(Set)

集合型(Set)は、基本的に順序を持たないリストである集合データ構造を実装します。Setクラスおよび集合を作成するためのテンプレートは、include\vcl\sysset.h ヘッダーファイルに定義されています。集合には、順序型(文字、整数、列挙型)の値だけを格納できます。最小値は 0 より大きくなければならず、最大値は 255 より小さくなければなりません。

集合を作成するには、3つのテンプレートパラメータを指定する必要があります。

集合の型(通常は char または enum 型)

最小値

集合が保持できる最小値

最大値

集合が保持できる最大値

集合をインスタンス化するごとに一意な型が作成されるので、typedef を使ってテンプレートから集合型を作成する方法が一般的です。

次に例を示します。

typedef Set <char, 'A','Z'> UPPERCASESet;
UPPERCASESet s;

C++Builder では、主に項目の順序が重要でない列挙プロパティに対して集合を使います。たとえば、Font プロパティには、集合として実装されている Style プロパティがあります。フォントのスタイルには、fsBold、fsItalic、fsUnderline、fsStrikeOut の 4つの値が可能です。以下に、ラベルのフォントのStyleプロパティを操作する例を示します。集合にメンバーを追加するためにオーバーロードされた “<<” 演算子とメンバーを削除するためにオーバーロードされた “>>” の使い方に注目してください。

void __fastcall TfrmSetDemo::chkbxBoldClick(TObject *Sender)
{
   if (chkbxBold->Checked)
      lbl->Font->Style = lbl->Font->Style << fsBold;
   else
      lbl->Font->Style = lbl->Font->Style >> fsBold;
}

    バリアントクラス(Variant)

バリアントクラスは、Delphiの組み込みバリアント型をモデルにしています。バリアント変数は、基本的に型を持たない変数で、自動的に異なる型の値を取ることができます。たとえば以下のコードでは、バリアント x は最初は整数として扱われますが、後半では文字列として扱われます。

void __fastcall TForm1::Button1Click(TObject *Sender)
{
   Variant x;

   x = 13;
   edtTest->Text = IntToStr( x + 12 );

   x = "Hello, world";
   ShowMessage( x );
}

バリアント型は便利ですが非常に効率が悪くなります。バリアント型は、OLE オートメーションサーバーオブジェクトへの参照を保持するように設計されています。

    AnsiString クラス、UnicodeString クラス

AnsiStringクラス および UnicodeStringクラスは、Delphiの長い文字列型との互換性を保つ目的で用意されています。AnsiString,UnicodeString は参照カウンタを保持します。すなわち、2つ以上の変数がメモリ上の同じ文字列を指す場合、文字列は自動的に参照カウンタを保持します。文字列によって割り当てられたメモリは、参照カウントが 0 にならないと解放されません。AnsiString,UnicodeString は NULL で終了し、初期値が提供されない場合は自動的に空の文字列に初期化されます。AnsiString,UnicodeString は VCL 関数との互換性を保つために必要なので、C++Builderでは多用されます。

たとえば以下のコードでは、AnsiStringクラス および UnicodeStringクラス が保持する文字列の一時的な先頭アドレスを c_str()メソッド を使ってアクセスしています。

AnsiStringの例

  char abuf[256];
  AnsiString astr("abcde");
  strcpy(&abuf[0], astr.c_str());
  ShowMessage(abuf);

UnicodeStringの例

  wchar_t ubuf[256];
  UnicodeString ustr(L"あいうえお");
  wcscpy(&ubuf[0], ustr.c_str());
  ShowMessage(ubuf);

    オープン配列

オープン配列は、VCL との型の互換性を保つために必要なもう1つのデータ型です。

    定義

オープン配列とは、関数のパラメータを渡すために作成される配列です。これにより、関数は可変数の引数をオープン配列として受け取ることができます。オープン配列は、Delphiで可変数の関数パラメータをサポートするために使用されているメカニズムです。

    オープン配列の「ヘルパー」マクロ

C++Builder では、オープン配列を「その場で」作成したり、既存の配列をオープン配列引数としてしようするためのいくつかのマクロが提供されます。

    OPENARRAY

一般に、OPENARRAYマクロは、オープン配列を引数に取る関数のパラメータとして「その場で」オープン配列を作成する必要がある場合に使用します。このマクロを使ってオープン配列を作成するには、オープン配列の型とカッコで囲んだ値(定数または変数)のリストをパラメータとして渡す必要があります。

以下に、整数型のオープン配列を宣言する例を示します。

OPENARRAY(int, (5, 7, 82, myIntVariable, 96))

また、VCLの関数には、array of const 型のパラメータを取るものがあります。オープン配列と同様に、これらの配列は一般に必要に応じて作成します。ただし、array of const は型が異なる複数の値を格納できます。array of const の型は常に TVarRec です。OPENARRAYマクロを使って array of const を作成する例を次に示します。

OPENARRAY(TVarRec, (myString, fontName, 34, 22.0, myVariant, "abc", 'd'))

    EXISTINGARRAY

EXISTINGARRAYマクロを使うと、すでに作成されている配列をオープン配列として渡すことができます。渡す配列は型が一致している必要があります。配列は、参照(関数が配列を変更できる)または値(コピーが作成されてコピーを変更できる)で渡すことができます。

以下に、EXISTINGARRAYマクロを使った例を示します。

EXISTINGARRAY(myExistingArrayOfTheCorrectType)

    まとめ

第七回は、C++の基礎知識の後編としまして「データ型」を中心に説明しました。

第八回は、C++BuilderでGUIプログラミングを行なう上で欠かせない「コンポーネント」を中心に解説する予定です。

なお、今回解説した内容についてもっと知りたい場合には、製品に付属するオンラインマニュアル、または、エンバカデロのWebサイトで参照可能なドキュメントをご活用ください。

Server Response from: ETNASC03