C++には、とても細かいルールが大量に存在する。
たとえば、あるクラスに、同じ型のdirect non-virtual base classとvirtual base classが存在する場合、メンバー初期化子は曖昧でill-formedとなる。
struct A { } ;
struct B: virtual A { };
struct C: A, B { C() ; };
C::C(): A() { } // ill-formed: which A?
関節のvirtual基本クラスはメンバー初期化子で初期化できる。しかし、直接のvirtualではない基本クラスと同じ型を使っている場合、曖昧でエラーとなる。
もちろん、これはC++という言語にとっては極めて重要なルールであるが、果たして、普通のプログラマーにとっても重要だろうか。これを知っていることで、よりよいコードを書けるのだろうか。
今書いているC++の参考書は、これらの些細なルールをも、漏れなく記載しているが、果たして本当にこんな説明が必要とされているのだろうか。
もちろん、ささいなことだが重要なルールもある。例えば、関数形式のキャストと宣言文とでは、文法が曖昧になる場合がある。その場合、宣言文として解釈可能な場合は、すべて宣言文として解釈するというルールがある。すなわち、以下のコードがill-formedになる。
int main()
{
    short a( 0 ) ;
    int b( int(a) ) ;
    b = 0 ; // ill-formed
}
なぜか、実は、このbというのは、int型の変数の宣言ではなくて、int型の引数をひとつ取り、int型を返す、関数bの宣言なのだ。aは仮引数名であり、aの周りにある括弧は、冗長である。
int main()
{
    int b( int a ) ; // 関数宣言
    b() ;
}
int b( int a ) { return 0 ; }
このような落とし穴は、説明する価値がある。もちろん、今書いているC++の参考書にも載せてある。おそらく、C++プログラマーならば大抵一度は引っかかるのではないだろうか。
 
No comments:
Post a Comment