クラス デザイナーでの C++ コードの使用

クラス デザイナーは、クラス ダイアグラム と呼ばれるビジュアル デザイン サーフェイスを表示します。クラス ダイアグラムは、プロジェクトのコード要素を視覚的に表現するものです。 クラス ダイアグラムを使用して、プロジェクト内のクラスおよびその他の型を設計し、視覚化できます。

クラス デザイナーは、次の C++ コード要素をサポートしています。

  • クラス (マネージド クラスの図形に似ていますが、複数の継承関係を持つことができるという点が異なります)

  • 匿名クラス (クラス ビューが匿名型に対して生成した名前を表示します)

  • テンプレート クラス

  • 構造体

  • 列挙型

  • マクロ (マクロの後処理ビューを表示します)

  • Typedef

Note

これは、モデリング プロジェクトで作成できる UML クラス図と同じではありません。 詳細については、「UML Class Diagrams: Reference」(UML クラス図: リファレンス) を参照してください。

クラス デザイナーの C++ クラス

クラス デザイナーは、C++ クラスをサポートし、Visual Basic および C# クラスの図形と同じ方法でネイティブの C++ クラスを視覚化します。ただし、C++ クラスは複数の継承関係を持つことができる点が異なります。 クラスの図形を展開して、表示されるクラスのフィールドとメソッドを増やしたり、図形を折りたたんでスペースを節約したりすることができます。

注意

クラス デザイナーは、共用体 (共用体の最大データ メンバーに必要な量のメモリしか割り当てられない特殊なタイプのクラス) をサポートしていません。

単純な継承

クラス ダイアグラムに複数のクラスをドラッグした場合、これらのクラスにクラス継承関係があると、矢印によって各クラスが接続されます。 矢印は、基底クラスの方向を指し示します。 たとえば、クラス ダイアグラムに以下のクラスが表示される場合、矢印によって各クラスが接続され、B から A が指し示されます。

class A {};
class B : A {};

また、クラス ダイアグラムに B クラスのみをドラッグしてから、B のクラス図形を右クリックして、 [基底クラスの表示] をクリックすることもできます。 このようにすると、基底クラスである A が表示されます。

多重継承

クラス デザイナーは、複数クラスの継承関係の視覚化をサポートしています。 多重継承は、派生クラスが複数の基底クラスの属性を持つときに使用されます。 多重継承の例を次に示します。

class Bird {};
class Swimmer {};
class Penguin : public Bird, public Swimmer {};

クラス ダイアグラムに複数のクラスをドラッグするときに、これらのクラスに複数クラスの継承関係があると、矢印によって各クラスが接続されます。 矢印は、基底クラスの方向を指し示します。

クラスの図形を右クリックして [基底クラスの表示] をクリックすると、選択したクラスの基底クラスが表示されます。

Note

[派生クラスの表示] コマンドは、C++ コードについてはサポートされていません。 派生クラスは、 [クラス ビュー] に移動し、型ノード、 [派生型] サブフォルダーの順に展開して、これらの型をクラス ダイアグラムにドラッグすることで表示できます。

複数クラスの継承の詳細については、「Multiple Inheritance」 (多重継承) と「Multiple Base Classes」 (複数の基底クラス) を参照してください。

抽象クラス

クラス デザイナーは、抽象クラス ("抽象基底クラス" ともいう) をサポートしています。 これらは、インスタンス化されることはありませんが、他のクラスを派生させることができるクラスです。 このドキュメントで既に説明した "多重継承" の例を使用すると、次のように、Bird クラスを個々のオブジェクトとしてインスタンス化できます。

int main()
{
   Bird sparrow;
   Bird crow;
   Bird eagle;
}

ただし、Swimmer クラスを個々のオブジェクトとしてインスタンス化するわけではありません。 そのクラスから、PenguinWhaleFish などのその他の種類の動物クラスを派生させるだけです。 この場合、Swimmer クラスを抽象基底クラスとして宣言することになります。

クラスを抽象として宣言するには、abstract キーワードを使用することができます。 抽象としてマークされているメンバー、または抽象クラスに含まれているメンバーは、仮想であり、抽象クラスから派生したクラスを使用して実装する必要があります。

class Swimmer abstract
{
   virtual void swim();
   void dive();
};

1 つ以上の純粋仮想関数を含めることで、クラスを抽象として宣言することもできます。

class Swimmer
{
   virtual void swim() = 0;
   void dive();
};

これらの宣言をクラス ダイアグラムで表示すると、クラス名の Swimmer とその純粋仮想関数である swim は、抽象クラスの図形で、 [抽象クラス] の表記とともに斜体で表示されます。 抽象クラス型の図形は、枠線が点線である点を除いて、通常のクラスと同じです。

抽象基底クラスからの派生クラスは、基底クラスの各純粋仮想関数をオーバーライドする必要があります。オーバーライドしない場合、派生クラスをインスタンス化できません。 そのため、たとえば、Fish クラスを Swimmer クラスから派生させた場合、Fishswim メソッドをオーバーライドする必要があります。

class Fish : public Swimmer
{
   void swim(int speed);
};

int main()
{
   Fish guppy;
}

このコードをクラス ダイアグラムで表示すると、クラス デザイナーFish から Swimmer へ継承線を描画します。

匿名クラス

クラス デザイナーは、匿名クラスをサポートしています。 匿名クラス型は、識別子なしで宣言されるクラスです。 これはコンストラクターもデストラクターも持てず、引数として関数に渡すこともできず、関数からの戻り値として戻すこともできません。 匿名クラスを使用して、次の例のように、クラス名を typedef 名に置き換えることができます。

typedef struct
{
    unsigned x;
    unsigned y;
} POINT;

構造体も匿名にできます。 クラス デザイナーは、匿名クラスと匿名構造体を、それぞれの型を表示するのと同じ方法で表示します。 匿名クラスと匿名構造体はユーザーが宣言および表示できますが、クラス デザイナーはユーザーが指定したタグ名を使用しません。 クラス ビューが生成する名前を使用します。 クラス ビューおよびクラス デザイナーでは、クラスまたは構造体は __unnamed という要素として表示されます。

匿名クラスの詳細については、「匿名クラス型」を参照してください。

テンプレート クラス

クラス デザイナーは、テンプレート クラスの視覚化をサポートしています。 入れ子になった宣言がサポートされています。 次の表は、一般的な宣言を示しています。

コード要素 クラス デザイナー ビュー
template <class T>

class A {};
A<T>

テンプレート クラス
template <class T, class U>

class A {};
A<T, U>

テンプレート クラス
template <class T, int i>

class A {};
A<T, i>

テンプレート クラス
template <class T, template <class K> class U>

class A {};
A<T, U>

テンプレート クラス

次の表は、部分的特殊化の例です。

コード要素 クラス デザイナー ビュー
template<class T, class U>

class A {};
A<T, U>

テンプレート クラス
template<class T>

class A<T, T> {};
A<T, T>

テンプレート クラス
template <class T>

class A<T, int> {};
A<T, int>

テンプレート クラス
template <class T1, class T2>

class A<T1*, T2*> {};
A<T1*, T2*>

テンプレート クラス

次の表は、部分的特殊化における継承の例です。

コード要素 クラス デザイナー ビュー
template <class T, class U>

class A {};

template <class TC>

class A<T, int> {};

class B : A<int, float>

{};

class C : A<int, int>

{};
A<T, U>

テンプレート クラス

B

クラス

(クラス A を指します)

C

クラス

(クラス A を指します)

次の表は、部分的特殊化テンプレート関数の例です。

コード要素 クラス デザイナー ビュー
class A

{

template <class T, class U>

void func(T a, U b);

template <class T>

void func(T a, int b);

};
A

func<T, U> (+ 1 overload)
template <class T1>

class A {

template <class T2>

class B {};

};

template<> template<>

class A<type>::B<type> {};
A<T1>

テンプレート クラス

B<T2>

テンプレート クラス

(B は、 [入れ子にされた型] の下のクラス A の中に含まれます)
template <class T>

class C {};

class A : C<int> {};
A

クラス

-> C<int>

C<T>

テンプレート クラス

次の表は、テンプレート継承の例です。

コード要素 クラス デザイナー ビュー
template <class T>

class C {};

template<>

class C<int> {

class B {};

}

class A : C<int>::B {};
A

クラス

->B

C<int>

クラス

(B は、 [入れ子にされた型] の下のクラス C の中に含まれます)

C<T>

テンプレート クラス

次の表は、標準特殊クラス接続の例です。

コード要素 クラス デザイナー ビュー
template <class T>

class C {};

template<>

class C<int> {};

class A : C<int> {};

class D : C<float> {};
A

クラス

->C<int>

C<int>

クラス

C<T>

テンプレート クラス

D

クラス

->C<float>
class B {

template <class T>

T min (const T &a, const T &b);

};
B

min <T>

クラス デザイナーの C++ 列挙体

クラス デザイナーでは、C++ の enum、およびスコープを持つ enum class 型はサポートされていません。 たとえば次のようになります。

enum CardSuit {
   Diamonds = 1,
   Hearts = 2,
   Clubs = 3,
   Spades = 4
};

// or...
enum class CardSuit {
   Diamonds = 1,
   Hearts = 2,
   Clubs = 3,
   Spades = 4
};

クラス ダイアグラムにおける C++ 列挙体の図形の形状と動作は構造体の図形に似ていますが、ラベルが [Enum] または [Enum class] である点と、青ではなくピンクである点、および左と上の余白に色つきの枠がある点が異なります。 列挙体の図形も構造体の図形も、角が直角になっています。

enum 型の使用法の詳細については、「列挙型」を参照してください。

クラス デザイナーにおける C++ の typedef

typedef ステートメントは、名前とその基になる型との間に間接参照のレイヤーを 1 つ以上作成します。 クラス デザイナーでは、キーワード typedef などで宣言される C++ の typedef 型をサポートしています。

typedef class coord
{
   void P(x,y);
   unsigned x;
   unsigned y;
} COORD;

この型を使用して、インスタンスを宣言することができます。

COORD OriginPoint;

クラスと構造体の図形

クラス デザイナーでは、C++ の typedef には、typedef で指定された型の図形があります。 ソースで typedef class が宣言されている場合、図形の角が丸くなり、Class のラベルが付きます。 typedef struct の場合、図形の角は四角で、Struct のラベルが付きます。

クラスと構造体は、その中で宣言されている入れ子になった typedef を持つことができます。 クラス デザイナーでは、クラスと構造体の図形は、入れ子になった typedef 宣言を入れ子にされた図形として表示できます。

typedef の図形では、右クリック メニュー (コンテキスト メニュー) として [関連として表示] および [コレクションの関連として表示] のコマンドをサポートしています。

クラスの typedef の例

class B {};
typedef B MyB;

C++ class typedef in Class Designer

構造体の typedef の例

typedef struct mystructtag
{
    int   i;
    double f;
} mystruct;

C++ struct typedef in Class Designer

名前のない typedef

名前のない typedef を宣言することもできますが、クラス デザイナーでは、指定したタグ名が使用されません。 クラス デザイナーではクラス ビューが生成する名前が使用されます。 たとえば、次の宣言は有効ですが、クラス ビュークラス デザイナーでは __unnamed という名前のオブジェクトで表示されます。

typedef class coord
{
   void P(x,y);
   unsigned x;
   unsigned y;
};

Note

クラス デザイナーでは、ソースの型が関数ポインターの typedef は表示されません。

C++ コード要素の制限事項について説明します

  • C++ のプロジェクトがロードされるとき、クラス デザイナーは読み取り専用で機能します。 クラス ダイアグラムは変更できますが、クラス ダイアグラムから変更内容をソース コードに保存することはできません。

  • クラス デザイナーは、ネイティブ C++ セマンティクスのみをサポートします。 マネージド コードにコンパイルされた C++ プロジェクトの場合、クラス デザイナーではネイティブ型のコード要素のみが視覚化されます。 このため、プロジェクトにクラス ダイアグラムを追加することはできますが、クラス デザイナーでは、IsManaged プロパティが true に設定されている要素 (つまり、値型および参照型) を視覚化することはできません。

  • C++ プロジェクトの場合、クラス デザイナーでは型の定義のみが読み取られます。 たとえば、ヘッダー (.h) ファイルで型を定義して、実装 (.cpp) ファイルでメンバーを定義するとします。 実装 (.cpp) ファイルで [クラス ダイアグラムで表示] を起動しても、クラス デザイナーには何も表示されません。 もう 1 つの例として、#include ステートメントを使用して他のファイルをインクルードし、実際のクラス定義は含まない .cpp ファイルで、[クラス ダイアグラムで表示] を起動する場合があります。この場合も、クラス デザイナーには何も表示されません。

  • IDL (.idl) ファイルでは COM インターフェイスとタイプ ライブラリが定義されますが、このファイルはネイティブ C++ コードにコンパイルされない限り、ダイアグラムには表示されません。

  • クラス デザイナーはグローバル関数とグローバル変数をサポートしていません。

  • クラス デザイナーは共用体をサポートしていません。 共用体は、最大データ メンバーが必要とする量のメモリしか割り当てられない、特殊なタイプのクラスです。

  • クラス デザイナーでは、intchar などの基本データ型は表示されません。

  • 現在のプロジェクトの外部で定義された型への正しい参照がプロジェクトにない場合、これらの型はクラス デザイナーで表示されません。

  • クラス デザイナーは、入れ子にされた型を表示することはできますが、入れ子にされた型とその他の型の間の関係は表示できません。

  • クラス デザイナーでは、void 型または void 型から派生した型を表示できません。

型解決および表示の問題のトラブルシューティング

ソース ファイルの場所

クラス デザイナーは、ソース ファイルの場所を追跡しません。 したがって、プロジェクト構造を変更するか、プロジェクト内でソース ファイルを移動すると、クラス デザイナーが型を見失うことがあります (特に typedef のソース型、基本クラス、または関連型の場合)。 クラス デザイナーはこの型を表示できませんなどのエラーが発生することがあります。 エラーが発生した場合は、変更または再配置したソース コードをもう一度クラス ダイアグラムにドラッグして再表示します。

更新およびパフォーマンスの問題

C++ プロジェクトの場合、ソース ファイルでの変更がクラス ダイアグラムに表示されるまでに 30 から 60 秒かかることがあります。 この遅延によって、クラス デザイナーで "選択内で型が見つかりませんでした" というエラーがスローされることもあります。 このようなエラーが表示された場合は、エラー メッセージで [キャンセル] をクリックし、クラス ビューにコード要素が表示されるまで待ちます。 その後、クラス デザイナーが型を表示できるようになります。

コードに加えた変更でクラス ダイアグラムが更新されない場合は、ダイアグラムを閉じて、再度開く必要がある場合があります。

型解決の問題

クラス デザイナーは、次のような理由により、型解決ができない場合があります。

  • 型が、クラス ダイアグラムを含むプロジェクトから参照されていないプロジェクトまたはアセンブリ内にあります。 このエラーを修正するには、型を含むプロジェクトまたはアセンブリへの参照を追加します。 詳細については、「プロジェクト内の参照の管理」を参照してください。

  • 型が正しいスコープ内にないため、クラス デザイナーが型を見つけられません。 コードに using ステートメント、imports ステートメント、または #include ステートメントが欠落していないことを確認します。 また、型 (または関連する型) を最初に配置した名前空間の外に移動していないことも確認します。

  • 型が存在しません (または、コメント アウトされています)。 このエラーを修正するには、型をコメント アウトまたは削除していないことを確認します。

  • この型は、#import ディレクティブで参照されるライブラリに含まれます。 生成したコード (.tlh ファイル) をヘッダー ファイルの #include ディレクティブに追加する、という代替手段があります。

  • クラス デザイナーが、入力した型をサポートしていることを確認します。 「C++ コード要素の制限事項」を参照してください。

型の解決に関する問題でよく表示されるエラーは、"クラス ダイアグラム '<要素>' の 1 つ以上のシェイプに対して、コードが見つかりませんでした" です。 このエラー メッセージは、必ずしもコードがエラーであることを意味しません。 クラス デザイナーで、コードを表示できないことだけを示しています。 次の方法を試してください。

  • 型がであることを確認します。 誤ってコメント アウトしたり、ソース コードを削除したりしていないことを確認します。

  • 型の解決を試みます。 型は、クラス ダイアグラムを含むプロジェクトから参照されていないプロジェクトまたはアセンブリ内にある場合もあります。 このエラーを修正するには、型を含むプロジェクトまたはアセンブリへの参照を追加します。 詳細については、「プロジェクト内の参照の管理」を参照してください。

  • クラス デザイナーが型を検出できるように、型が正しいスコープ内にあることを確認します。 コードに using ステートメント、imports ステートメント、または #include ステートメントが欠落していないことを確認します。 また、型 (または関連する型) を最初に配置した名前空間の外に移動していないことも確認します。

ヒント

その他のトラブルシューティング情報については、「クラス デザイナーのエラー」を参照してください。