C ++はオブジェクト指向プログラミングに適していないことを、ここでの質問に対する回答の1つで(どこにあるか覚えていない)読みました。あなたはその機能またはそのようなものを利用できるが、純粋にOOPの意味ではないという言及がありました(私は実際にその人の意味を本当に理解していませんでした)。
これにはいくつかの真実があります。もしそうなら、なぜですか?
C ++はオブジェクト指向プログラミングに適していないことを、ここでの質問に対する回答の1つで(どこにあるか覚えていない)読みました。あなたはその機能またはそのようなものを利用できるが、純粋にOOPの意味ではないという言及がありました(私は実際にその人の意味を本当に理解していませんでした)。
これにはいくつかの真実があります。もしそうなら、なぜですか?
回答:
で説明したように、「オブジェクト指向」という用語でアランケイは本当に何を意味しましたか?、Alan Kayは、メッセージの受け渡しがOOPの重要なビットであると考えましたが、「クラスを持つC」(後にC ++になりました)には欠けているビットです。C ++は動作が少しだけの構造体ですが、SmalltalkまたはObjective-Cのオブジェクトは、送信されるメッセージをどう処理するかを決定できるという点で「インテリジェント」です。Smalltalk風のオブジェクトが実装されていないメッセージを受信した場合、それを遅延的に追加したり、別のオブジェクトにメッセージを転送したり、任意のことを実行したりできます。
オブジェクト指向の方法でC ++が提供するのは、virtual
メソッドと、それらのメソッドが呼び出される方法に関係するポリモーフィズムです。コンパイラは、class
仮想メソッドを持つデータ型(または)を検出すると、各仮想メソッドのスロットを持つvtableを構築します。仮想メソッドを実装するサブクラスは、実装を正しいスロットに配置するため、クライアントコードは、特定の関数に至るまで解決するのではなく、実行するコードを探す仮想テーブルの場所を知るだけで済みます。つまり、C ++は事実上複数のディスパッチの形式を持っていますが、すべてコンパイラに実装されており、Smalltalk風のシステムほどの能力はありません。
メッセージの受け渡しをOOPの基本と考えると、C ++でそれを行うことはできますが、決して簡単ではありません。OTOH OOPを使用して、データをそのデータに作用する関数に関連付けることを意味する場合、C ++で問題ありません。
カプセル化、継承、およびポリモーフィズムを意味するようにOOPを定義する場合、C ++ は OOPをサポートします。
ただし、C ++はOOPにはあまり優れていません。理由の1つは、ポリモーフィズムがヒープ割り当てオブジェクトに依存することが多いことです。ヒープ割り当てオブジェクトは、(スマートポインターの使用にもかかわらず)ガベージコレクション言語での作業がより自然です。
ただし、C ++が優れているのは、汎用プログラミングです。C ++を使用すると、テンプレートベースの関数型プログラミング手法により、効率の高い汎用コードを簡単に作成できます。
C ++はSimulaからOOP機能を借りました。Simula開発者IIRCの1人以上は、C ++は彼らが念頭に置いていたものではないとコメントしました。
C ++には抽象化のための優れたツールがありますが、オブジェクト指向言語というよりは混合パラダイム言語です。オブジェクト指向機能はありますが、「厳密なOOP」ではない選択肢があります。
C ++で得られるいたずらな「オプトアウト」の1つは、メソッドの遅延バインディングではなく早期バインディングを使用することです。これが可能であるだけでなく、これがデフォルトです。Javaでは、「最終」は関連していますが、いくつかの点でよりクリーンです(些細なパフォーマンスのオーバーヘッドを回避するだけではない方法で意図を指定します)、そしてそれはデフォルトではありません。
いくつかの点で、C ++はまだ実験中の初期の実験の兆候を示しています。それでも、他のOOP言語では得られない多くの利点を備えた、優れたツールです。
すべてを強制的にクラスの一部にすることは、必ずしもすばらしいオブジェクト指向コードを生み出すとは限りません。
貧しい手続き型プログラマーにJavaでプログラミングするように依頼すると、おそらくどこかにクラスを取り、静的なメインメソッドを与えて、そこに1000行のコードを挿入します。私はそれを見たことを知っています。
Javaにはswitchステートメントがあります。私はswitch( type ) { case typeA: bundles_of_code; break; case typeB: bundles_of_other_code; break }
C ++とJavaコードの両方でなどを見てきました。
C ++は多くのオブジェクト指向の概念をサポートしていますが、その標準はそれによって定義されていませんが、私はあなたの目的が何であるかに大きく依存すると思います。
C ++の主な「貧弱な」セマンティックは、クラスのコピー構築を許可し、それによってオブジェクトが別のクラスに変換されることです。これを無効にすることはできますが、関数から返すことはできません。幸いなことに、これはC ++ 0xで対処されています。
私は感情に同意しませんが、C ++の型システムは純粋なOOPではなく、「すべてがオブジェクトである」ことではないのは事実です。(特に)数字は、たとえばSmalltalkのように簡単に拡張できません。たとえば、「2 + 2」の意味を再定義することはできません(ただし、「two + two」の意味は再定義できます)。
しかし、ほとんどの人がおそらく意味するのは、多くの人が非オブジェクト指向のコードをC ++で記述しますが、「OOP」言語を使用しているため、オブジェクト指向であると信じているということです。それは真実ではない。しかし、私の意見では、Smalltalkで恐ろしい命令型コードを書くことができ、C ++でのきちんとしたOOP設計よりも優れているわけではありません。
C ++に対するAlan Kayの完全に有効な異議は、C上のマクロ言語であるということでした。
「メッセージの受け渡し」の概念は、クラスのインスタンスがメモリに保持され、呼び出し可能なメソッドを公開するという考え方にすぎません。C ++では、関数へのポインターを保持するvtableを使用して、メッセージの受け渡しが*シミュレートされます。
メッセージの受け渡しはC ++には存在しないと言うと、メッセージの受け渡しはsmalltalkやJavaのような他の言語の不可欠な部分であるということです。
これは高度にセマンティックな言語設計の議論であり、質問者の経験レベルを少し超えていると思われます。
C ++を嫌う理由は1000ありますが、C ++を愛する理由はほとんどありません。
完璧なハンマーと完璧な釘を探すのではなく、構築するのに最適な家を見つけてから、経験が必要な適切なツールを見つけてください。
また、システムプログラミングでアランケイが恐れているのは「純粋なOOP」ではないことを覚えておくことが重要です。これは実際にはC ++の強みです。それぞれ自分自身に...
私の見解では、それは定義の問題ではなく、ユーザビリティの問題ではありません。
オブジェクトは、複雑なプログラムの読み取り、書き込み、および推論を容易にするための抽象化です。実用的なプログラマーにとって、言語が「オブジェクト指向」の特定の正式な定義(競合するものがあるようです!)のすべての基準を満たしているかどうかは、提供するツールが考えるのに適しているかどうかほど重要ではありません前述のオブジェクトの観点からプログラムを作成します。つまり、OOPの想定される生産性のメリットを実際に享受します。
C ++では、オブジェクトはひどく漏れやすい抽象概念であり、多くの場合、プログラマーは、それらのオブジェクトがメモリ内でどのように構成されているかに関する厄介な問題を抱えることになります。たとえば、C ++ Frequently Questioned Answersは、この批判を(とりわけ)提供しています。
C ++以外のOOシステム、およびC ++を「OO」と見なす特別な方法で解釈される「カプセル化、継承、ポリモーフィズム」トリニティ以外のOO定義に習熟することは、開業医にとって非常に有益です。たとえば、境界チェックやガベージコレクションがない環境はオブジェクト指向環境ではないという主張は、C ++に慣れている人にとってはとんでもないことです。しかし、多くの観点から、それは非常に理にかなっています。誰かがオブジェクトを上書きできる場合、「カプセル化」はどこにありますか?オブジェクトを破棄すると、ぶら下がり参照やメモリリークが発生する可能性がある場合、システムはどのように「オブジェクト指向」であるか ?特定の場所と時間にどのようなオブジェクトが配置されているかを伝える機能はどうですか?あなたはソフトウェアがオブジェクトで動作すると言います-それらはどこにありますか?そして、見つけられない場合、ソフトウェアをどのようにデバッグするのですか?
C ++はオブジェクト指向ですが、不快で不完全です。ユーザーは、データが誤ったビットではなく、実際のオブジェクトのように振る舞うように多くの努力を払う必要があります。とは言っても、多くのコードはその寿命にわたってC ++で記述されており、そのほとんどはクラスと動的ディスパッチを使用しているため、実際のOOPに使用できることは自明のことです。
ここにグラハム・リーが最も賛成票を投じた理由があります。繰り返しますが、C ++クラスは、メッセージの受け渡しを実行しないという意味で、実際にはオブジェクトではないようです。これが、C ++やoopを学んでいる人を大いにつまずかせるものだと思います。人々は、オブジェクト指向は「これ」であると言われ、C ++はそれを違うやり方で行うと言われます。さて、C ++はOOPをこれまでとは異なりませんでした。このように考えると、C ++クラスの意味を理解することはできません。つまり、抽象化と動的な振る舞いを組み込むことにより、手続き型パラダイムを単に改善しただけです。したがって、C ++クラスは基本的に手続き型であり、手続き型のパラダイムを改良したものであるか、C構造体のより高度なバージョンです。
C ++は、最も知覚力が低いという非常に現実的な意味で、地球上で最も愚かな言語です。それ自体は知りません。
C ++のオブジェクトシステムはコンパイル時に非常にハードワイヤードで固定されているため、メッセージパッシング、イントロスペクション、リフレクション、動的ディスパッチ、レイトバインディングなどを含むOOPの元の概念とは非常に異なります。C ++とSmalltalkの共通点は、少しの語彙だけです。