2013-11-28

CとC++の違い: Basic Concepts編

京都C++勉強会の宣伝のために、CとC++の違いを、少しづつ解説することにした。

江添とボレロ村上の京都C++勉強会が、12月16日に行われる。これを書いている時点では、まだ空きがあるので、最新のC++14の新機能と、コンパイル時レイトレーシングを勉強したければ、ATNDで参加申し込みをせよ。

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

C++はCの完全互換ではない。Cのあまり良くない部分は、変更して改良した。ここでは、そのような変更点のうち、互換性に特に問題のあるものを取り上げる。

tentative definitionの有無

C言語には、tentative definitionという機能があった。以下のようなコードが合法になる。

int i ;
int i ; // well-formed in C, ill-formed in C++

C++にはOne Definition Ruleがあるので、このようなコードは違法である。

C言語に存在するtentative definition機能は、定義の後で初期化できるという機能を提供している。

struct X { X * next ; } ;

X a ; // 定義
X b = { &a } ;
X a = { &b } ; // 初期化

C++では、基本型とユーザー定義型で別々の初期化ルールを設けるのを防ぐために、tentative definition機能はCから受け継がなかった。

structにはスコープがある

C++では、structは構造体ではなくクラスであり、新たなスコープを作る。Cではstructは、単なる構造体であり、その名前探索の挙動が異なる。

ただし、通常はこの差を気にする必要はない。

ファイルスコープ内で、const修飾され、extern指定されていない変数は、C++では内部リンケージとなる。Cでは、外部リンケージとなる。

// file1

// Cでは外部リンケージ
// C++では内部リンケージ
const int x = 0 ;
// file2

// Cではfile1のxを指す
// C++は違う
extern const int x ;

C++では、constオブジェクトは、コンパイル時定数となることもあるので、初期化子が必須なこともあるので、このような変更がなされた。

C++では、main関数を再帰的に呼び出すことはできず、アドレスを取得することもできない。

C++では、main関数は特別なものとして認識され、呼び出すことはおろか、アドレスを得ることさえできない。Cでは、そのような制限はない。

C++でこのような制約がある背景事情としては、mainは特別な扱いであるべきで、その実装方法に関して、C++の実装に、通常のような関数として扱えるような制約を持たせたくないというものがあるそうだ。

Cで書かれたmain関数を再帰呼び出ししたりアドレスを得たりするコードを移植する際には、単にmain関数から呼び出される別名で同じ仮引数の関数を作ればいい。そもそも、main関数を再起呼び出ししたりアドレスを得たりするような実用的なコードは、あまり存在しないだろう。

C++にはCompatible type(互換型)が存在しない

Cには、互換型というものが存在する。例えば、タグ名以外はすべて同一の構造体などが該当する。C++は強い静的型付けを持っているので、そのような互換型は存在しない。

Cでは、そのような型非安全なコードは多いのではないかと思う。

明日も、宣伝のために標準型変換の変更点を解説する。

江添とボレロ村上の京都C++勉強会が、12月16日に行われる。これを書いている時点では、まだ空きがあるので、最新のC++14の新機能と、コンパイル時レイトレーシングを勉強したければ、ATNDで参加申し込みをせよ。

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

No comments: