C++

出典: Wikipedio


Template:Infobox プログラミング言語 C++シープラスプラス、日本では略してシープラプラシープラ、あるいはシータスタスなどとも)は、汎用プログラミング言語の一つである。高度な機能を使用してもプログラムの実行性能が低下しすぎないように、言語仕様・ライブラリに様々な工夫が施されている。1990年代以降、C++は、最もよく利用される商用のプログラミング言語の1つとなっている。静的な型システムを持ち、手続き型プログラミングデータ抽象オブジェクト指向プログラミングジェネリックプログラミングといった複数のプログラミングパラダイムをサポートするマルチパラダイムプログラミング言語である。

C++は、1983年にベル研究所のコンピュータ科学者であったビャーネ・ストロヴストルップが、C言語の拡張として開発した。当時の名前は「C with Classes」(クラス付きのC言語)というものであった。拡張はクラスの追加に始まり、仮想関数多重定義多重継承テンプレート例外処理といった機能が続いていった。C++言語の標準は1998年にISO/IEC 14882:1998として承認され、現在のバージョンは2003年に制定されたISO/IEC 14882:2003である。新しいバージョンが策定中で、非公式ではあるが「C++0x」と呼ばれている。(それは2000年代中に制定され、正式に「C++09」と呼称されるであろうことを見越した仮称であったが、2000年代中には実現しなかった。)

目次

歴史

ストロヴストルップはC with Classesの開発を1979年に開始した。彼は大規模なソフトウェアの開発に有用な特徴をSimulaが備えていることに気がついたが、Simulaは実行速度が遅く実用的でなかった。一方でBCPLは実行速度こそ速かったものの、大規模なソフトウェア開発を念頭に置いた場合にあまりにも低級であった。これらの事情を鑑みて、ストロヴストルップは当時既に汎用的な言語であったC言語にSimulaの特徴を取り入れることを試みた。この取り組みにあたってはALGOL68AdaCLUML等の言語の影響も受けている。最初はクラスと派生クラス、型検査機構の強化、インライン関数、デフォルト引数の機能を、Cfrontを介してC言語に追加した。1985年10月に最初の商用リリースがなされた<ref name="invention">Template:Cite web</ref>。

1983年にはC with ClassesからC++に名称を変更した。この際に、仮想関数と、関数と演算子の多重定義参照型、const型、ユーザー制御可能な自由領域メモリ制御、型検査機構の改良、BCPL形式(「//」による)の行単位のコメントアウトなどの機能が追加された。1985年には『The C++ Programming Language』の初版が出版された(邦訳『プログラミング言語C++』(1988年))。この時点では公式な標準が策定されていなかった為に、この本が事実上のリファレンスとなった。1989年C++のヴァージョン2.0として、多重継承抽象クラス、静的メンバ関数constメンバ関数、protectedメンバ等の機能が追加されたものがリリースされた。1990年に『The Annotated C++ Reference Manual (ARM)』が出版され、将来の標準化の土台となるものを提供した。後に追加された機能にはテンプレート例外処理名前空間、新形式のキャストブール型が含まれた。

C++言語の進化に伴い、標準ライブラリもまた進化していった。C++標準ライブラリに最初に追加されたのは、従来のC言語の printfscanf といった関数を置き換えるしくみを提供する、ストリームI/Oライブラリであった。それ以降の標準ライブラリへの追加で最も重要なものはStandard Template Library (STL)である。

標準規格

長年にわたる作業の後、ANSIとISOの合同委員会はC++言語を1998年に標準化した(ISO/IEC 14882:1998)。1998年の標準の公式なリリースから数年間に渡って委員会は不具合の報告を続け、2003年に訂正版を出版した。2005年に「Library Technical Report 1」 (TR1)というテクニカルレポートがリリースされた。これは標準の公式な一部ではないが、次のバージョンのC++に含まれると期待される、標準ライブラリへの数多くの拡張を与えている。現在メンテナンスされているC++コンパイラの大部分が、TR1のサポートに取り組んでいる。

2003年12月に制定された日本工業規格JIS X 3014:2003(プログラム言語 C++)は、ISO/IEC 14882:2003 (E)の翻訳である。

将来

C++に対しては、今もなお要望が絶えない。特にBoostはC++の方向性の決定に大きく貢献し、さらにC++標準化委員会へ改良すべき点などを意見している。現在はマルチパラダイムプログラミングをより自然に行えるようにすることに力が注がれており、たとえばBoostでは、C++の関数型プログラミングメタプログラミングの可能性を模索している。

C++ 0xと呼ばれている新しいバージョンのC++標準ではこれらが取り込まれることになると見られている。

C++という名称

この名称はRick Mascittiの功績で、最初に使用されたのは1983年の12月である。初期の研究期間では、開発中の言語は「C with Classes」と呼ばれていた。最終名は、変数の値を1つ加算する、C言語の「++」演算子からの派生である。また一般的な命名規則での「+」の使用は、機能強化されたコンピュータプログラムを意味する。ストロヴストルップによれば「この名前は、C言語からの変更の革新的な本質を示している」ということである。C+は、より初期の無関係なプログラミング言語の名前であった。

ストロヴストルップは著書「The C++ Programming Language」の前文で名前の起源を語り、ジョージ・オーウェルの「1984年」の付録から「C++」が連想されるかもしれないと付け加えている。新語法という架空の言語の解説に宛てられた3つの章の中に、科学技術に関する専門用語とジャーゴンの解説に宛てられた「C vocabulary」という章がある。新語法で「ダブルプラス」は最上級の修飾語である。ゆえに新語法で「C++」は「最も極端な専門用語またはジャーゴン」という意味になるであろう。

1992年、Rick Mascittiは名前について非公式に質問されると、彼はおふざけのつもりで命名したという旨の回答をした。彼はこの言語の正式な名称になるとは夢にも思わなかったのである。

哲学

ビャーネ・ストロヴストルップは著書『C++の設計と進化(1994)』でC++を設計する際に用いたルールを述べている。

  • C++はCと同等の実行効率と移植性を持つ静的に型付けされた汎用言語である。
  • C++は直接的かつ包括的に複数のプログラミングスタイル (手続き型プログラミング抽象化オブジェクト指向ジェネリックプログラミング)をサポートする。
  • C++はもしプログラマが間違っている可能性があったとしてもプログラマに選択の余地を与える。
  • C++は可能な限りC言語との互換性を持ち、C言語からスムーズに移行できる。
  • C++はプラットフォームに固有な機能や汎用的でない機能の実装を避ける。
  • C++は利用しない機能についてはオーバーヘッドが生じない(ゼロオーバーヘッドの原則)。
  • C++は高級な実行環境を必要としない。

C++のコンパイラがどのようにコードを出力しメモリのレイアウトを決めるのかということについてはInside the C++ Object Model (Lippman, 1996)に記載されている。ただしコンパイラが出力するコードの仕様はコンパイラ制作者の裁量に任されている。

標準ライブラリ

Template:Main

1998年に施行されたANSI/ISO C++ 規格は言語仕様とライブラリの2つのパートで構成される。ライブラリ規格の大半はStandard Template Library (STL)とC言語の標準ライブラリの改良版についての内容である。標準規格以外にも様々なライブラリが数多く存在し、リンカを使用することにより、C言語FORTRANPascalBASICのような言語を用いて作成されたライブラリを利用できる。規格外のライブラリが利用できるかどうかはコンパイラに依存する。

C++標準ライブラリはC++向けに若干の最適化が施されたC言語標準ライブラリを含んでいる。C++標準ライブラリの大部分はSTLである。 コンテナ(可変長配列リストなど)、コンテナを配列のように扱えるようにするイテレータ、検索やソートを行うアルゴリズムといった有用なツールが提供されている。さらにmapやmultimapのような連想配列や、setやmultisetのようなソート済みコンテナも提供され、これらは全てインターフェイスに互換性がある。テンプレートを用いることにより、あらゆるコンテナ(またはイテレータで定義したシーケンス)に適用できる汎用的なアルゴリズムを記述できる。C言語と同様にライブラリ機能には#include ディレクティブを使ってヘッダファイルを読み込むことによってアクセスする。C++には69本の標準ヘッダファイルがあるが、このうち19本については非推奨となっている。

STLは標準規格に採用される前はヒューレット・パッカードの(一時はシリコングラフィックスの)商用ライブラリであった。STLは標準規格の単なる一部分に過ぎず規格書にSTLという表記は見られないが、STL以外の部分(入出力ストリーム、国際化、デバッグ機能、C言語標準ライブラリ等)と区別するために今でも多くの人がSTLという用語を使っている。

大半のC++コンパイラはSTLを含むC++標準ライブラリの実装を提供している。STLPortのようなコンパイラ非依存のSTLも存在する。様々な目的でC++標準ライブラリを独自に実装しているプロジェクトは他にもある。

C++の標準ライブラリは大きく次のように分けられる。多種多様な実行環境が存在することを考慮して、スレッドGUIに関するライブラリは標準に含まれていない。

  • 入出力
  • 文字列
  • 現地化(ロケール)
  • 数値演算
  • STL
  • その他(例外処理や日付と時刻の処理など)

外部ライブラリ

以下に、C++で広く使われていると思われるライブラリを挙げる。

特徴

C言語に、オブジェクト指向プログラミングをサポートするための改良が加えられたものといえるが、他のオブジェクト指向を念頭において作られた言語と違い、旧来のCと同様に手続き型言語としても扱えるという特徴がある(このとき、C++をbetter Cというふうに呼ぶことがある)。また基本的にC言語に対して上位互換性がある。初期のC++はCへのトランスレータとして実装された(すなわち、C++プログラムを一旦Cプログラムに変換してからコンパイルしていた)。

その後、先祖であるC言語の標準規格制定時には、const修飾など、C++の機能がC言語に取り入れられることにもなった。現在ではC言語とC++との間には厳密な互換性はない。特にC99の出現により、C言語との互換性は完全に失われている。

次のような多種多様な機能を持っており、言語仕様は大変複雑である。言語仕様を完全に満たしているコンパイラは、現在数えるほどしかない。

ここから、よりオブジェクト指向を強化し、「なんでもあり」ではない代わりに分かりやすくスマートな設計を目指した新たな言語(JavaD言語など)が作られることとなった。

Hello World!

C++はC言語及びそのプリプロセッサの構文をほぼ継承している。以下のサンプルはストロヴストルップが記述した標準C++ライブラリのストリーム機能を用いて標準出力に出力するHello worldプログラムである<ref></ref><ref>Open issues for The C++ Programming Language (3rd Edition) - このコードはストロヴストルップ自身による訂正文からの引用(633ページ)。std::endl'\n'に改めている。またmain関数がデフォルトで0を返す件についてはwww.research.att.com及びwww.delorie.com/djgpp/ を参照されたし。このデフォルト仕様はmain関数のみであり他の関数にはない。</ref>

<source lang="cpp">

  1. include <iostream>

int main() {

  std::cout << "Hello, world!\n";

} </source>

演算子と演算子のオーバーロード

C++には四則演算、ビット演算、参照、比較、論理演算などの30を超える演算子がある。メンバーアクセス演算子(.と.*)のような一部の例外はあるが、大半の演算子はユーザー定義によるオーバーロードが可能である。オーバーロード可能な演算子が豊富に揃えられているためC++を一種のドメイン固有言語として利用できる。またオーバーロード可能な演算子はスマートポインタのような先進的な実装テクニックに欠かせないものとなっている。演算子をオーバーロードしても演算の優先順位は変化せず、また演算子のオペランドの数も変化しない(ただし指定したオペランドが無視される可能性はある)。

テンプレート

Template:Main

C++ではテンプレートを使ってジェネリックプログラミングができる。C++は関数テンプレートとクラステンプレートの両方をサポートしている。テンプレートは型、コンパイル時定数またはその他のテンプレートによってパラメタライズできる。テンプレートはコンパイル時にインスタンス化される。コンパイラは関数やクラスをインスタンス化するためにテンプレート仮引数を特定の値に置き換える。テンプレートはジェネリックプログラミングテンプレートメタプログラミング、コード最適化などのために利用される強力なツールであるが、一定のコストを伴う。各テンプレートのインスタンスはテンプレート仮引数毎にテンプレートコードのコピーを生成するためコードサイズが肥大化する。コンパイル時に型の情報を削除して単一のテンプレートインスタンスを生成するランタイム型のジェネリクスを実装したJavaなどの言語とは対照的である。

テンプレートとマクロはいずれもコンパイル時に処理される言語機能であり条件に基づいたコンパイルが行われるが、テンプレートは字句の置き換えに限定されない。テンプレートはC++の構文と型を解析し、厳密な型チェックに基づいた高度なプログラムの流れの制御ができる。マクロは条件コンパイルに利用できるが、新しい型の生成、再帰的定義、型の評価などは行えないため、コンパイル前のテキストの置き換えや追加・削除といった用途に限定される。つまりマクロは事前に定義されたシンボルに基づいてコンパイルの流れを制御できるものの、テンプレートとは異なり独立して新しいシンボルを生成することはできない。テンプレートは静的な多態(下記参照)とジェネリックプログラミングのためのツールである。

C++のテンプレートはコンパイル時におけるチューリング完全なメカニズムである。これはテンプレートメタプログラムを用いて実行する前にコンピュータが計算可能なあらゆる処理を表現できることを意味している。

概略すれば、テンプレートはインスタンス化に必要な引数を明確にしなくても記述できるコンパイル時にパラメタライズされる関数またはクラスである。インスタンス化した結果は、テンプレート仮引数に指定した型に特化した形で記述されたコードと全く等価になる。これによりテンプレートは、汎用的かつおおまかに記述された関数及びクラス(テンプレート)と特定の型に特化した実装(インスタンス化されたテンプレート)の依存関係を解消し、パフォーマンスを犠牲にすることなく抽象化できる手段を提供する。

オブジェクト

C++はC言語オブジェクト指向プログラミングをサポートするための改良を加えたものといえる。C++のクラスにはオブジェクト指向言語で一般的な抽象化カプセル化継承多態の4つの機能がある。オブジェクトは実行時に生成されるクラスのインスタンスである。クラスは実行時に生成される様々なオブジェクトのひな形と考えることができる。

カプセル化

カプセル化とは、データ構造を保証し、演算子が意図したとおりに動作し、クラスの利用者が直感的に使い方を理解できるようにするためにデータを隠蔽することである。クラスや関数はC++の基礎的なカプセル化のメカニズムである。クラスのメンバはpublic、protected、privateのいずれかとして宣言され明示的にカプセル化できる。publicなメンバはどの関数からでもアクセスできる。privateなメンバはクラスのメンバ関数から、またはクラスが明示的にアクセス権を与えたフレンド関数からアクセスできる。protectedなメンバはクラスのメンバおよびフレンド関数に加えてその派生クラスのメンバからもアクセスできる。

オブジェクト指向では原則としてクラスのメンバ変数にアクセスする全ての関数はクラスの中にカプセル化されなければならない。C++ではメンバ関数およびフレンド関数によりこれをサポートするが、強制はされない。プログラマはメンバ変数の一部または全体をpublicとして定義でき、型とは無関係な変数をpublicな要素として定義できる。このことからC++はオブジェクト指向だけでなく、モジュール化のような機能分割のパラダイムもサポートしているといえる。

一般的には、全てのデータをprivateまたはprotectedにして、クラスのユーザに必要最小限の関数のみをpublicとして公開することがよい習慣であると考えられている。このようにしてデータの実装の詳細を隠蔽することにより、設計者はインターフェイスを変更することなく後日実装を根本から変更できる <ref> </ref> <ref> </ref>。

継承

継承を使うと他のクラスの資産を流用できる。基底クラスからの継承はpublic、protected、privateのいずれかとして宣言する。このアクセス指定子により、派生クラスや全く無関係なクラスが基底クラスのpublicおよびprotectedメンバにアクセスできるかどうかを決定できる。普通はpublic継承のみがいわゆる派生に対応する。残りの二つの継承方法はあまり利用されない。アクセス指定子を省略した場合、構造体はpublic継承になるのに対し、classではprivate継承になる。基底クラスをvirtualとして宣言することもできる。これは仮想継承と呼ばれる。仮想継承は基底クラスのインスタンスが1つだけ存在することを保証するものであり、多重継承の曖昧さの問題を避けることができる。

多重継承はC++の中でもしばしば問題になる機能である。多重継承では複数の基底クラスから1つのクラスを派生できる。これにより継承関係が複雑になる。例えば"Flying Cat"クラスは"Cat"クラスと"Flying Mammal"クラスから派生できる。JavaC#では、基底クラスの数を1つに制限する一方で、複数のインタフェースを継承でき、これにより制約はあるものの多重継承に近い機能を実現できる。インタフェースはクラスと異なりメンバ関数を宣言できるのみであり、関数の実装やメンバ変数は定義できない。JavaとC#のインタフェースや抽象クラスはC++の抽象基底クラスと呼ばれる関数宣言のみを持つクラスに相当する。JavaやC#の継承モデルを好むプログラマは、非抽象クラスからのみクラスを派生させる方法を選択できる。この場合は抽象基底クラスのメンバ関数を必ず明示的に定義しなければならず、またこのクラスを継承することはできない。

多態

Template:Main

多態(ポリモーフィズム)はよく多用されているインターフェイスの機能であり、様々な状況下でオブジェクトに異なる振る舞いをさせることができる。

C++は静的な多態動的な多態の両方をサポートする。コンパイル時に解決される静的な多態は実行時には考慮されないのに対し、ランタイム時に解決される動的な多態はパフォーマンス的に不利である。

静的な多態

関数のオーバーロードは名称が同じ複数の関数を宣言できる機能である。ただし引数は異なっていなければならない。関数は引数の型や数で区別される。同名の関数はコードの文脈によってどの関数が呼ばれるのかが決まる。関数の戻り値の型で区別することはできない。

関数を宣言する際にプログラマはデフォルト引数を指定できる。関数を呼び出すときに引数を省略した場合はデフォルト引数が適用される。関数を呼び出すときに宣言よりも引数の数が少ない場合は、左から右の順で引数の型が比較され、後半部分にデフォルト引数が適用される。たいていの場合は1つの関数にデフォルト引数を指定するよりも引数の数が異なる関数をオーバーロードする方が望ましい。

C++のテンプレートではより洗練された汎用的な多態を実現できる。特にCuriously Recurring Template Patternにより仮想関数のオーバーライドをシミュレートした静的な多態を実装できる。C++のテンプレートは型安全かつ チューリング完全であるため、 テンプレートメタプログラミングによりコンパイラに条件文を再帰的に解決させて実行コードを生成させることにも利用できる。

動的な多態

派生

基底クラスへのポインタ変数及び参照は、正確に型が一致するオブジェクトだけでなく、その派生クラスのオブジェクトを示すことができる。これにより配列やコンテナは複数の型へのポインタを保持できる。ポインタ変数は実行時に値が割り当てられるためこれは実行時の話である。

dynamic_castは基底オブジェクトから派生オブジェクトへの変換を安全に行うための演算子である(派生オブジェクトから基底オブジェクトへの変換ではキャストは必要ない)。この機能は実行時型情報 (RTTI)に依存している。オブジェクトが特定の派生オブジェクトであることがあらかじめわかっている場合はstatic_castでキャストすることもできる。static_castは純粋にコンパイル時に解決されるため動作が速くRTTIを必要としない。

仮想関数

基底クラスの関数を派生クラスでオーバーライドした場合、実際に呼び出される関数はオブジェクトの型によって決定される。派生クラスによってオーバーライドでされるのは引数の数や型が同じ関数である。基底クラスのポインタのみが与えられた場合、コンパイラはオブジェクトの型をコンパイル時に特定できず正しい関数を呼び出せないため、実行時にこれを特定する。これをダイナミックディスパッチと呼ぶ。仮想関数やメソッド<ref> </ref>により、オブジェクトに割り当てられた実際の型に従って、最上位の派生クラスで実装した関数が呼び出される。一般的なC++コンパイラは仮想関数テーブルを用いる。オブジェクトの型が判明している場合はスコープ解決演算子を利用して仮想関数テーブルを使わないようにバイパスすることもできるが、一般的には実行時に仮想関数の呼び出しを解決するのが普通である。

標準のメンバ関数に加え、オーバーロードした演算子やデストラクタも仮想関数にできる。原則的にはクラスが仮想関数を持つ場合はデストラクタも仮想関数にすべきである。コンストラクタやその延長線上にあるコピーコンストラクタはコンパイルされた時点でオブジェクトの型が確定しないため仮想関数にできない。しかしながら、派生オブジェクトへのポインタが基底オブジェクトへのポインタとして渡された場合に、そのオブジェクトのコピーを作らなければならない場合は問題が生じる。このような場合はclone()関数(またはそれに準じる物)を仮想関数として作成するのが一般的な解決方法である。clone()は派生クラスのコピーを生成して返す。

= 0を関数宣言の閉じ括弧とセミコロンの間に挿入することによりメンバ関数を純粋仮想関数にできる。純粋仮想関数を持つクラスは純粋仮想クラスと呼ばれ、このクラスからオブジェクトを生成することはできない。このような純粋仮想クラスは基底クラスとしてのみ利用できる。派生クラスは純粋仮称関数を継承するため、派生クラスのオブジェクトを生成したい場合は全ての純粋仮想関数をオーバーライドして実装しなければならない。純粋仮想関数を持つクラスのオブジェクトを生成しようと試みるようなプログラムは行儀が悪い。

単一行コメント

かつてC言語とC++との分かりやすい差異として、// で始まり改行で終わる、単一行コメントの有無があった。

単一行コメントはもともと、C言語の祖先にあたるBCPLに含まれていた仕様である。現在のC++のコンパイラの多くがC言語のコンパイラとしても使えるようになっているのと同様に、C言語が生まれて間もない頃は、C言語に加えB言語やBCPLのコンパイルができるコンパイラが用いられていた。それらコンパイラは、C言語のソースであってもBCPLと同様に単一行コメントが使用できるよう独自の拡張がなされていたため、BCPLの単一行コメントに慣れ親しんでいたプログラマ達は、C言語でも単一行コメントを使い続けた。その慣習がC++の誕生時まで生き残っていたため、C++では単一行コメントを「復活」させることになったのである。

そのためもあって、C言語での仕様外の単一行コメントの使用は半ば常習と化し、現在ではC99によって、C言語でも正式に単一行コメントがサポートされるようになった。 (//に対応していない古い仕様のCコンパイラでもcppを対応したものに変更することにより使用可能)

C++ソースコードの処理とパーサ

LALR(1)のような旧式のパースアルゴリズムを用いてC++のパーサを記述することは比較的難しい<ref>Template:Cite web</ref>。その理由の一つはC++の文法がLALRではないことである。このため、コード分析ツールや、高度な修正を行うツール(リファクタリングツールなど)は非常に少ない。この問題を取り扱う方法としてLALR(1)でパースできるように改良されたC++の亜種(SPECS)を利用する方法がある。GLRパーサのようにより強力でシンプルなパーサもあるが処理が遅い。

パースはC++を処理するツールを作成する際の最も難しい問題ではない。このようなツールはコンパイラと同じように識別子の意味を理解しなければならない。従ってC++を処理する実用的なシステムはソースコードをパースするだけでなく、各識別子の定義を正確に適用し(つまりC++の複雑なスコープのルールを正確に取り扱い)、型を正しく特定できなければならない。

いずれにせよC++ソースコード処理ツールが実用的であるためには(GNU GCCVisual C++で使われているような)様々なC++の方言を取り扱えなければならず、適切な分析処理やソース変換やソース出力などが実装できなければならない。GLRのような先進的なパースアルゴリズムとシンボルテーブルを組み合わせてソースコードを変換する方法を利用すればあらゆるC++ツールを開発できる。

互換性

C++規格に準拠したコンパイラを開発するのは一般的に難しい。何年にも渡りC++に部分的に準拠した様々なコンパイラが作られ、テンプレートの部分特殊化などの部分で実装にばらつきがあった。最近のメジャーなC++コンパイラは1998年の規格にほぼ準拠している<ref>Template:Cite web</ref>。規格に完全に準拠する実装は恐らくまだ無いと考えられる。

テンプレートの宣言と実装を分離できるようにするためのexportは問題のキーワードの一つである。規格がリリースされてから5年後の2003年前半にComeau C/C++が初めてexportを実装した。2004年にBorland C++ Builder Xexportを実装した。これらのコンパイラはいずれもEDGのフロントエンドをベースにしていた。大半のコンパイラで実装されていないexportは多くのC++関連書籍(例えばBeginning ANSI C++ Ivor Horton著)にサンプルが記されているが、exportが記載されていることによる問題は特に指摘されていないということも注目すべき点である。GCCをはじめとするその他のコンパイラでは全くサポートしていない。Herb SutterはC++の標準規格からexportを削除することを推奨していたが<ref> Template:PDFlink</ref>、最終的にこれを残すことで決定している<ref>Template:Cite web</ref>。

コンパイラ開発者の裁量で決められる範囲を確保するため、C++標準化委員会は名前修飾例外処理などの実装に依存する機能の実装方法を決定しないことに決めた。この決定の問題はコンパイラが異なるとオブジェクトファイルの互換性が保証されない点である。特定の機種やOSでコンパイラの互換性を持たせようとするABI<ref>Template:Cite web</ref>のような非標準の規格もあり、一部のコンパイラではこうした準規格を採用している。

C言語との互換性

C++は基本的にC言語の上位互換であるが、厳密には異なる<ref>Template:Cite web</ref>。C言語で記述された大半のプログラムはC++でコンパイルできるように簡単に修正できるが、C言語では正当でもC++では不正になる部分や、C++とは動作が異なる部分が若干存在する。

例えば、C言語では汎用ポインタ( void* )は他のポインタに暗黙で変換できるが、C++では変換を明示する必要がある。またC++では newclass といった数多くの新しいキーワードが追加されたが、移植の際に元のC言語のプログラムでそれらが識別子(例えば変数名)として使われていると、問題になる。

最新のC言語の標準規格であるC99ではこうした非互換性の一部が解決されており、//形式のコメントや宣言とコードの混在といったC++の機能がC言語でサポートされている。その一方でC99は、可変長配列、複素数型の組み込み変数、指示初期化子、複合リテラルといった、C++でサポートしていない数多くの新機能が追加されている<ref>Template:Cite web</ref>。しかしながらC99で追加された新機能の一部はC++の次期バージョンであるC++0xに含まれる見込みである。

C言語のコードとC++のコードを混在させるためにはCリンケージを利用する必要があり、関数をextern "C" { ... }のブロックの中で宣言しなければならない。Cリンケージを利用した関数については、C++名前修飾がされず、名前修飾に依存している関数オーバーロード機能は利用できない。

主なC++処理系

脚注

Template:Reflist

参考文献

関連項目

Template:Wikibooks

Template:CProLang

Template:プログラミング言語af:C++ an:C++ ar:سي++ (لغة برمجة) az:C++ bat-smg:C++ be:C++ bg:C++ bn:সি++ br:Areg C++ bs:C++ bug:C++ ca:C++ cs:C++ cv:Си++ da:C++ de:C++ el:C++ en:C++ eo:C++ es:C++ et:C++ eu:C++ fa:سی++ fi:C++ fr:C++ ga:C++ gan:C++ gl:C++ he:C++ hi:सी++ hr:C++ hu:C++ hy:C++ ia:C++ id:C++ is:C++ it:C++ jv:C++ ka:C++ kaa:C++ ko:C++ la:C++ lb:C++ lt:C++ lv:C++ mk:C++ ml:സി++ mr:सी प्लस प्लस प्रोग्रॅमिंग लँग्वेज ms:C++ my:C++ new:सी++ nl:C++ nn:C++ no:C++ oc:C++ pl:C++ pt:C++ ro:C++ ru:C++ sah:C++ sh:C++ simple:C++ sk:C++ sl:C++ sq:C++ sr:C++ sv:C++ ta:சி++ te:సీ ప్లస్ ప్లస్ tg:C++ th:ภาษาซีพลัสพลัส tk:C++ programmirleme tr:C++ uk:C++ uz:C++ vi:C++ zh:C++ zh-yue:C++

個人用ツール