2010-11-27

abstract classで知らなかったこと、付記、派生と継承の違い

以下のコードはwell-formedである。

struct Non_abstract { virtual void f() { } } ; 
struct Abstract : Non_abstract { void f() = 0 ; } ;

abstractクラスは、abstractクラスではないクラスから派生されることができる。その際、pure virtual functionではないvirtual functionを、pure virtual functionとしてオーバーライドすることができる。

これが何の役に立つのか分からない。ただ、pure virtual functionがあればabstract classであるなどという、あまり文法的に美しくないC++の仕様からすると、わざわざこの挙動を禁止する理由が見当たらなかったのだろうか。

ところで、今まで私は、派生と継承の違いを明確に理解していなかった。実際、この二つの言葉は、一般に、あまり区別されていないように思う。では、C++の規格ではどうなのか。

まず、派生というのは、derivedの訳語である。継承というのは、inheritedの訳語である。

規格では、あるクラスは、基本クラスから派生される(be derived from)という表現を用いている。個人的に、受身の表現は分かりにくい。例えば、「DerivedクラスはBaseクラスから派生されている(The Derived class is derived from the Base class.)」といえば、以下のようなコードを意味する。

struct Base { } ;
struct Derived : Base { } ;

ところで、このような場合、俗に、「DerivedはBaseを継承している」などと言われることもある。これは、規格に照らし合わせると、誤りである。継承という言葉は、クラスの派生関係には用いられない。C++では、クラスに対して、継承という言葉を用いるのは誤りである。

では、継承とは何か。規格では、基本クラスのメンバーは、派生クラスに、継承される(be inherited by)という表現を用いている。例えば、「Baseクラスのメンバー関数fは、Derivedクラスに、継承されている(The Base class's member function f is inherited by the Derived class)」といえば、以下のようなコードを意味する。

struct Base { void f() ; } ;
struct Derived : Base { } ;

派生の場合と同じく、このような場合に、「Baseクラスのメンバー関数fはDerivedクラスに派生されている」というのは誤りである。このような言葉は、聞いたことがない。思うに、継承という言葉は、派生クラスに対する基本クラスという意味を表す際に、受身にならずに使えるため、クラスの派生関係にも使われてしまったのだろう。

まとめると、クラスは派生するものである。クラスのメンバーは継承するものである。用語は正しく使わねばならない。

No comments: