2013-12-06

CとC++の違い: クラス編

京都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で参加申し込みをせよ。

江添とボレロ村上の京都C++勉強会 | 集客ならイベントアテンド

No comments: