[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

5.7 シグネチャを使った型抽象

GNU C++ ではキーワード signature を使って、 完全抽象クラスインターフェースをデータ型として定義することができる。 シグネチャポインタを使って、この抽象化を実際のクラスと関係付けることが できる。シグネチャを使いたい場合は、GNU コンパイラに ‘-fhandle-signatures’ オプションを指定して実行する。 (このオプションを指定すると、もう一つのキーワード sigof も、 将来の拡張に備えて、予約する。)

大雑把に言って、シグネチャは型の抽象化あるいはクラスのインターフェース である。他の言語にも同様の機能を持つものがある。C++ のシグネチャは ML のシグネチャ、Haskell の型クラス、Modula-2 の定義モジュール、 Modula-3 のインターフェースモジュール、Emerald の抽象型、 Trellis/Owl の型モジュール、Scratpad II のカテゴリ、 POOL-I の親戚である。シグネチャについてのもっと詳細な議論については、 Signatures: A Language Extension for Improving Type Abstraction and Subtype Polymorphism in C++。 これは、Gerald Baumgartner and Vincent F. Russo によるもので、 Tech reportCSD–TR–95–051, Dept. of Computer Sciences, Purdue University, August 1995 に掲載されている。少々改訂したバージョンが、 Software—Practice & Experience, 25(8), pp. 863–889, August 1995) にある。 この技術報告書は、匿名 FTP により、 ftp.cs.purdue.edu の ‘pub/gb/Signature-design.ps.gz’ から入手できる。

文法的には、シグネチャの宣言はメンバ関数宣言とネストした型宣言の 集まりである。 例えば、以下のシグネチャ宣言は、メンバ関数 ‘int foo ()’ と ‘int bar (int)’ を持つ、新しい抽象型 S を定義する。

 
signature S
{
  int foo ();
  int bar (int);
};

シグネチャ型には実装の定義はないので、シグネチャの実体を直接書くこと はできない。代わりに、必要とするインターフェースを含む任意のクラスへの ポインタを シグネチャポインタ として定義することができる。 このようなクラスはシグネチャ型を実装する。

あるクラスを S の実装として使うには、そのクラスが、 パブリックなメンバ関数 ‘int foo ()’ と ‘int bar (int)’ を 持っていることを保証しなければならない。 このクラスは、パブリックでもパブリックでなくも、他のメンバ関数も 持つことができる。シグネチャで宣言されているものを提供している限り、 シグネチャ型の実装として適切なのである。

例えば、C がシグネチャ S の要件を満たすクラスであると する(CS適合する)。すると、

 
C obj;
S * p = &obj;

これはシグネチャポインタ p を定義し、それをC 型のオブジェクトを 指すように初期化する。 メンバ関数を ‘int i = p->foo ();’ のように呼び出すと、 ‘obj.foo ()’ が実行される。

標準の C++ では、抽象仮想クラスが幾らか似た機能を提供している。 代わりにシグネチャを使うことの主な利点は二つある。

  1. 下位型を取ることにより継承に依存しなくなる。クラスや T 型の シグネチャは、S で宣言されているメンバ関数が全て、T にも ある限り、どんな継承階層構造であっても、シグネチャ型 S の 下位型である。このため、クラスの継承階層構造を反映した型を 使うことを強制される代わりに、任意の継承(実装)階層構造から完全に 独立している下位型の階層構造を定義できる。
  2. シグネチャを使うと、既存のクラス階層をシグネチャ型の実装として 使うことができる。もしこのクラス階層がコンパイルされた形でしか 利用できないとすると、抽象仮想クラスを使うときに困ることになる。 抽象仮想クラスは既存のクラス階層の一番上に後から取り付けることは できないからである。このため、インターフェースクラスを その抽象仮想クラスの下位型として書く必要がある。

シグネチャについての詳細を一つ述べる。 シグネチャ宣言には、メンバ関数宣言と同様、メンバ関数定義も 含めることができる。シグネチャの、完全に定義されているメンバ関数は デフォルト実装と呼ばれる。クラスは、適合するために特定の インターフェースを含む必要はない。 例えば、クラス C は以下のシグネチャに適合し得る。

 
signature T
{
  int f (int);
  int f0 () { return f (0); };
};

これは、C がメンバ関数 ‘int f0 ()’ を実装していても していなくても良い。C::f0 を定義すれば、その定義が優先する。 定義しなければ、S::f0 のデフォルト実装が適用される。


This document was generated using texi2html 1.78.