京都C++勉強会の宣伝のために、CとC++の違いを、少しづつ解説することにした。
江添とボレロ村上の京都C++勉強会が、12月16日に行われる。これを書いている時点では、まだ空きがあるので、最新のC++14の新機能と、コンパイル時レイトレーシングを勉強したければ、ATNDで参加申し込みをせよ。
江添とボレロ村上の京都C++勉強会 | 集客ならイベントアテンド
今回は、クラス編だ。C++ではクラスを導入したせいで、C言語の構造体とは少し違ったスコープのルールになっている。
C++では、クラス宣言はクラス名をスコープに持ち込む。C言語ではクラス名を持ち込まないし、外部スコープの名前を隠すこともない。
int x[99] ; // #1 void f() { struct x { int i ; } ; // #2 // Cでは#1のサイズ // C++では#2のサイズ sizeof( x ) ; }
これはなぜかというと、C言語では、宣言した構造体名は必ず、structキーワードをつけて使うからだ。C++では、基本型とユーザー定義型の文法に違いを持たせたくないため、クラス名だけで使えるようにしている。そのため、クラス名がスコープに導入される。
C++では、int型のビットフィールドの型は符号付きである。Cでは符号は実装依存である。
int型のビットフィールドの符号を実装依存にするのは、テンプレートの実体化のさいに問題になる。一貫性を保つため、非依存名でも、符号つきになるように、実装の自由度を狭めた。
いくらビットフィールドとはいえ、"int"なのに、符号付きかどうか実装依存というCの定義は不思議だ。
C++では、ネストされたクラス名の属するスコープは、直前の外側のクラススコープである。Cでは、直前の外側のクラスが属するスコープである。
struct Outer { struct Inner { } ; } ; // Cでは合法 // C++では違法 struct Inner i ;
C言語はわけがわからない。
どうやら、当時のC言語における構造体というのは、そもそもスコープがどうというものではなかったようだ。そもそも、名前もtypedef名で与えるコードが一般的だったようだし、全然別の言語なのだろう。
C++では、メンバー関数を導入したことにより、クラスは厳格にスコープを持たなくてはならなくなった。それがこの違いを生んだのだろう。それにしても、Cは汚い。
C++では、クラス名ですでにtypedef名が使われた場合、そのtypedef名が再宣言されてはならない。
typedef int I ; struct S { I i ; // typedef名をすでに使う // Cでは合法 // C++では違法 int I ; } ;
たしかこれはD&Eにも書いてあった内容のはずだ。クラスはその完全な定義が明らかになった後に、再び銭湯から解釈した時に、メンバー名の意味が変わってはならないというルールだ。それにしても、Cは汚い。
江添とボレロ村上の京都C++勉強会が、12月16日に行われる。これを書いている時点では、まだ空きがあるので、最新のC++14の新機能と、コンパイル時レイトレーシングを勉強したければ、ATNDで参加申し込みをせよ。
No comments:
Post a Comment