回答:
まず、「STL」は正式な用語ではなく、コンテナがなかったときにC ++標準ライブラリに含めることが提案されたライブラリの名前です。それは本質的にコンテナーとアルゴリズムのテンプレートを提供します。
現在、これらのコンテナとアルゴリズムのテンプレートは...テンプレートなので、必要に応じて型を生成します。ユーザーの観点からは継承に依存しません。
ただし、標準ライブラリは、実装ではなく、基本的にライブラリのインターフェイスを指定します。多くのSTL実装は、実装でオブジェクト指向を少し使用しますが、実装のソースコード(本質的にはテンプレートコードであるため公開する必要がある)に飛び込まない場合、ユーザーには表示されません。
オブジェクト指向を正当化する仮想メンバー関数がテンプレートと矛盾することを知りましたが、これは正しいですか?
いいえ、それらは直交する概念であり、非常に異なる長所と短所のセットを提供します。実際、C ++では、そのような言語を使用する主な利点の1つは、両方を使用できることと、一方を使用しても他方を使用してキャンセルしないことです。それも非常に大きな利点です。たとえば、C ++で最も興味深いイディオムの1つは、テンプレートと継承の両方を使用するCRTPです。継承部分では、基本クラスとして、共通の動作とデータを使用していくつかの型を拡張できるという考え方です。テンプレートパーツでは、子ごとに特定の基本クラスを生成する必要があるため、CRTPクラスを基本として使用して、すべてのクラスへのポインターを持つことはできません。これは非常に便利で、本来あるべきではないところに継承をいじることを許しません。
また、イベントタイプもリスナータイプも知らない非常に一般的なイベントディスパッチシステムを実装しましたが、内部の動的コードと静的コードを組み合わせて、適切なランタイムタイプに対応する適切な内部タイプを生成できました。
そして、それがポイントです。「オブジェクト指向」が常に必要なわけではありません。実際、ほとんどの場合、それをまったく必要とせず、いくつかのタイプを定義し、それらをある種の抽象エンジン(構成)の別の部分として直接使用する必要があります。テンプレートと呼ばれる一般的なコードが常に必要なわけではありません。関数を一般化して、いくつかの無関係な型に適用することが必要になる場合があります。それらが関連している場合は、代わりに基本クラスを使用でき、テンプレートは必要ありません。
それらは異なる利点と完全に異なるコストを持っているため、複雑な問題を解決するために組み合わせるのに適しています。
STLは、ランタイムオブジェクトの階層ではなく、特定のタイプに関連するタイプ(コンテナー)と関数(アルゴリズム)を提供することに関する問題の良い例です。標準ライブラリでは、ストリームはオブジェクト指向に典型的な方法で作成されます。これは、さまざまな動作/容量を組み合わせたサブストリームクラスを定義できるようにさまざまなことを行うストリームクラスの階層です。そこでは、オブジェクト指向は有用ですが、STLのようになりたいという人もいます(私はこのテーマの専門家ではありません)。
ですから、それらをドライバーとハンマーのような非常に異なるツールと考えてください。C ++では、1つのツールのみを考慮して考えることはできません。
実際、STLはジェネリックプログラミングパラダイムを主流に取り入れました。
私は約教えられたときに、オブジェクト指向プログラミングの 15年前(一部の教授による)パラダイム、私は3つの重要な柱は、カプセル化、継承、ポリモーフィズム(おそらくとして適格である必要があり、後者今日教えられたランタイム、多型)ながら、現在ウィキペディアは 、 OOP特性の定義として、データの抽象化、カプセル化、メッセージング、モジュール性、ポリモーフィズム、および継承を示しています。もちろん、STLはカプセル化などの一部を使用しますが、構造化プログラミングパラダイムの特徴である関数も使用します。しかし、STLが構造化プログラミングであると主張する人は誰もいません。
C ++の最も強力な機能の1つは、多くのプログラミングパラダイム(構造化、オブジェクト指向、ジェネリック、関数型プログラミングなど)をサポートしていることと、それらを混ぜて混ぜると最も明るくなることに注意してください。
STLPortのインタビューからAlexander Stepanovを引用するには:
STLはオブジェクト指向ではありません。オブジェクト指向は、人工知能とほぼ同じでっちあげだと思います。これらのオブジェクト指向の人々からの興味深いコードはまだ見ていません。[...] OOPは哲学的に不健全だと思います。それはすべてがオブジェクトであると主張しています。たとえそれが本当であるとしても、それはそれほど興味深いことではありません-すべてがオブジェクトであると言っても、何も言わないことです。OOPは方法論的に間違っていると思います。
とはいえ、継承とポリモーフィズムを使用して個々の実装を行うこともできます。たとえば、iterator
からconst_iterator
への暗黙的な変換をサポートするためにから派生した実装を見てきましiterator
たconst_iterator
。ただし、派生は設計の特徴でも、設計で必要なものでもありません。
結論:オブジェクト指向のコードを使用してSTLの一部を実装できますが、STL自体の設計は(特に)オブジェクト指向ではありません。
いいえ、私はSTLは特にオブジェクト指向ではない、と言えば、関数型プログラミングスタイルにさらにマップします。特に:
同様に、コンテナー自体がモナドであると主張することもできます
vector<string>(1,"Foo")
他の質問については、C ++のOO部分とテンプレート部分は別々であり、仮想関数はテンプレートを持つことを排除しません。STLの場合、デザインは仮想関数の使用を選択しません。
std::vector<int>
オブジェクト指向ではないと信じる理由はありません。
OOPは誰がOOPの定義を求めているかによって異なります。OOPは悪名高く誤定義された用語であり、OOPを構成するものとそうでないものについては十分なコンセンサスがないためです。
Javaパーソンの観点からは、C ++のアルゴリズムとコンテナーライブラリはランタイムポリモーフィズムを処理せず、クラス継承を使用せず、構文がOOP-yに見えないため、答えはおそらく「いいえ」です。
一方、機能的なプログラミング担当者に尋ねると、答えは「はい」です。
オブジェクト指向プログラミング(OOP)は、アプリケーションとコンピュータープログラムを設計するために、「オブジェクト」(データフィールドとメソッドとその相互作用で構成されるデータ構造)を使用したプログラミングパラダイムです。プログラミング手法には、データの抽象化、カプセル化、メッセージング、モジュール性、多態性、継承などの機能が含まれる場合があります。最近のプログラミング言語の多くは、少なくともオプションとしてOOPをサポートしています。
これらはすべて、C ++の標準ライブラリ、特にコンテナとアルゴリズムを扱う部分で実現または支援されています。特に、アルゴリズムはカプセル化と抽象化(したがってモジュール性)を強化し、テンプレートを使用することで多態性になります。
オブジェクト指向を正当化する仮想メンバー機能を学びました
一体どこで聞いたの?
オブジェクト指向の重要な原則は、カプセル化と抽象化です。virtual
関数は、それを実現するための1つの手段にすぎません。実際のオブジェクトの向きにはまったく必要ありません。実際、テンプレートは完全に適切な手段です。それは継承ではないかもしれませんが、それでも一種の多態性です。そして、いくつかのクラスはどちらも必要としません。
標準ライブラリのコンテナは完全にオブジェクト指向です。それらはインターフェースからのすべての不必要な詳細をカプセル化し、実装を合理的に可能な限り最大限に抽象化します。
OOPの実装自体は、「オブジェクト」の意味を定義しない限り、何も意味しません。オブジェクトが値である場合(いわゆるOOP言語のほとんどのようにエンティティではなく、C ++が想定している場合)、STLはOOPであり、それ以外の場合はありません。
次のコードフラグメントを想定します。
Person a("joe");
Person b = a;
同じ生きている人の 2つの表現ですかa
、それとも同じ名前の2つの生きているペソンだけですか?b
オブジェクトは何ですか?a
、b
または彼らが代表する生きている人?
また、C ++の継承は、オブジェクトの継承(抽象化)とは異なる技術的な集約メカニズムです。特定の分野を課す場合、2つは一致する可能性があります(オブジェクトはすべて間接的にアクセス可能であり、すべて置換可能である、つまりすべての関連メソッドが仮想であることを意味します)。そうでない場合、異なる目的をターゲットにすることができます(C ++継承は「暗黙的な構成」にすぎません) )
テンプレートは、(特殊化により)動的タイプ(仮想関数に基づく)ではなく静的タイプに基づく「置換」メカニズムを提供することもできます。この意味で-コンパイル時に同じ専門分野が使用される場合-コンパイル時OOPを提供します。
本質的に、C ++の集計およびディスパッチングスキームは、それ自体がOOPであるか、またはOOPを正当化します。彼らは他のこともできます。OOPは、オブジェクトを一緒に記述および関連付けるための抽象的な方法論です。これらの関係は、オブジェクトタイプがランタイムの実行に依存する場合は継承と仮想ディスパッチにマッピングでき、コンパイル時にオブジェクトタイプを定義できる場合はテンプレートの特殊化と暗黙的な変換にマッピングできます。継承は、参照とポインタ間の暗黙的な変換を提供する方法の1つにすぎません。