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