STLはOOで実装されていますか?


8

Adaptor、STLに実装されたIteratorなど、いくつかの設計パターンがあります。

それは、STLがOOの概念で実装されているということですか?
OOとC ++のテンプレートパーツの関係は何ですか?

オブジェクト指向を正当化する仮想メンバー関数がテンプレートと矛盾することを知りましたが、これは正しいですか?


4
STLの設計者は有名な反OOです。en.wikipedia.org/wiki/Alexander_Stepanov#Criticism_of_OOP
stonemetal

回答:


11

まず、「STL」は正式な用語ではなく、コンテナがなかったときにC ++標準ライブラリに含めることが提案されたライブラリの名前です。それは本質的にコンテナーとアルゴリズムのテンプレートを提供します。

現在、これらのコンテナとアルゴリズムのテンプレートは...テンプレートなので、必要に応じて型を生成します。ユーザーの観点からは継承に依存しません。

ただし、標準ライブラリは、実装ではなく、基本的にライブラリのインターフェイスを指定します。多くのSTL実装は、実装でオブジェクト指向を少し使用しますが、実装のソースコード(本質的にはテンプレートコードであるため公開する必要がある)に飛び込まない場合、ユーザーには表示されません。

オブジェクト指向を正当化する仮想メンバー関数がテンプレートと矛盾することを知りましたが、これは正しいですか?

いいえ、それらは直交する概念であり、非常に異なる長所と短所のセットを提供します。実際、C ++では、そのような言語を使用する主な利点の1つは、両方を使用できることと、一方を使用しても他方を使用してキャンセルしないことです。それも非常に大きな利点です。たとえば、C ++で最も興味深いイディオムの1つは、テンプレートと継承の両方を使用するCRTPです。継承部分では、基本クラスとして、共通の動作とデータを使用していくつかの型を拡張できるという考え方です。テンプレートパーツでは、子ごとに特定の基本クラスを生成する必要があるため、CRTPクラスを基本として使用して、すべてのクラスへのポインターを持つことはできません。これは非常に便利で、本来あるべきではないところに継承をいじることを許しません。

また、イベントタイプもリスナータイプも知らない非常に一般的なイベントディスパッチシステムを実装しましたが、内部の動的コードと静的コードを組み合わせて、適切なランタイムタイプに対応する適切な内部タイプを生成できました。

そして、それがポイントです。「オブジェクト指向」が常に必要なわけではありません。実際、ほとんどの場合、それをまったく必要とせず、いくつかのタイプを定義し、それらをある種の抽象エンジン(構成)の別の部分として直接使用する必要があります。テンプレートと呼ばれる一般的なコードが常に必要なわけではありません。関数を一般化して、いくつかの無関係な型に適用することが必要になる場合があります。それらが関連している場合は、代わりに基本クラスを使用でき、テンプレートは必要ありません。

それらは異なる利点と完全に異なるコストを持っているため、複雑な問題を解決するために組み合わせるのに適しています。

STLは、ランタイムオブジェクトの階層ではなく、特定のタイプに関連するタイプ(コンテナー)と関数(アルゴリズム)を提供することに関する問題の良い例です。標準ライブラリでは、ストリームはオブジェクト指向に典型的な方法で作成されます。これは、さまざまな動作/容量を組み合わせたサブストリームクラスを定義できるようにさまざまなことを行うストリームクラスの階層です。そこでは、オブジェクト指向は有用ですが、STLのようになりたいという人もいます(私はこのテーマの専門家ではありません)。

ですから、それらをドライバーとハンマーのような非常に異なるツールと考えてください。C ++では、1つのツールのみを考慮して考えることはできません。


8

実際、STLはジェネリックプログラミングパラダイムを主流に取り入れました。

私は約教えられたときに、オブジェクト指向プログラミングの 15年前(一部の教授による)パラダイム、私は3つの重要な柱は、カプセル化、継承、ポリモーフィズム(おそらくとして適格である必要があり、後者今日教えられたランタイム、多型)ながら、現在ウィキペディアは OOP特性の定義として、データの抽象化、カプセル化、メッセージング、モジュール性、ポリモーフィズム、および継承示しています。もちろん、STLはカプセル化などの一部を使用しますが、構造化プログラミングパラダイムの特徴である関数も使用します。しかし、STLが構造化プログラミングであると主張する人は誰もいません。

C ++の最も強力な機能の1つは、多くのプログラミングパラダイム(構造化、オブジェクト指向、ジェネリック、関数型プログラミングなど)をサポートしていることと、それらを混ぜて混ぜると最も明るくなることに注意してください。


7

STLPortのインタビューからAlexander Stepanovを引用するには:

STLはオブジェクト指向ではありません。オブジェクト指向は、人工知能とほぼ同じでっちあげだと思います。これらのオブジェクト指向の人々からの興味深いコードはまだ見ていません。[...] OOPは哲学的に不健全だと思います。それはすべてがオブジェクトであると主張しています。たとえそれが本当であるとしても、それはそれほど興味深いことではありません-すべてがオブジェクトであると言っても、何も言わないことです。OOPは方法論的に間違っていると思います。

いえ、継承とポリモーフィズムを使用して個々の実装を行うことできます。たとえば、iteratorからconst_iteratorへの暗黙的な変換をサポートするためにから派生した実装を見てきましiteratorconst_iterator。ただし、派生は設計の特徴でも、設計で必要なものでもありません

結論:オブジェクト指向のコードを使用してSTLの一部を実装できますが、STL自体の設計は(特に)オブジェクト指向ではありません。


3

いいえ、私はSTLは特にオブジェクト指向ではない、と言えば、関数型プログラミングスタイルにさらにマップします。特に:

  • std :: algorithmsはメソッドではなくフリー関数です
  • 彼らはしばしば関数オブジェクトをとります:: 高次関数です
  • 彼らはどんなコンテナでも動作します
  • std :: transformはマップ、X_if関数はフィルター、std :: accumulateは折りたたみ/縮小

同様に、コンテナー自体がモナドであると主張することもできます

  • テンプレートのインスタンス化は型構築です
  • シーケンスには少なくともユニットコンストラクタがあります。 vector<string>(1,"Foo")
  • fmapはstd :: transformです
  • バインドまたは結合、あるいはその両方が実装可能です(そのままでは提供されません)
  • bind / joinの合理的な実装はモナドの法則に適合します

他の質問については、C ++のOO部分とテンプレート部分は別々であり、仮想関数はテンプレートを持つことを排除しません。STLの場合、デザインは仮想関数の使用を選択しません。


フリー関数とメソッドの大部分は構文上の違いであり、それらが機能的であるというだけで、反対にオブジェクト指向ではないという意味ではありません。
Konrad Rudolph、

さらに、アルゴリズムは機能する場合がありますが、それがstd::vector<int>オブジェクト指向ではないと信じる理由はありません。
DeadMG

3

OOPは誰がOOPの定義を求めているかによって異なります。OOPは悪名高く誤定義された用語であり、OOPを構成するものとそうでないものについては十分なコンセンサスがないためです。

Javaパーソンの観点からは、C ++のアルゴリズムとコンテナーライブラリはランタイムポリモーフィズムを処理せず、クラス継承を使用せず、構文がOOP-yに見えないため、答えはおそらく「いいえ」です。

一方、機能的なプログラミング担当者に尋ねると、答えは「はい」です。

ウィキペディアでOOPを定義する方法次のとおりです。

オブジェクト指向プログラミング(OOP)は、アプリケーションとコンピュータープログラムを設計するために、「オブジェクト」(データフィールドとメソッドとその相互作用で構成されるデータ構造)を使用したプログラミングパラダイムです。プログラミング手法には、データの抽象化、カプセル化、メッセージング、モジュール性、多態性、継承などの機能が含まれる場合があります。最近のプログラミング言語の多くは、少なくともオプションとしてOOPをサポートしています。

これらはすべて、C ++の標準ライブラリ、特にコンテナとアルゴリズムを扱う部分で実現または支援されています。特に、アルゴリズムはカプセル化と抽象化(したがってモジュール性)を強化し、テンプレートを使用することで多態性になります。


ただし、OOPの主な機能の1つであるこれらのコンテナーでは継承を使用する必要があります。
sbi

1
@sbi私は相続を赤いニシンだと考えています。OOPとは実際には、継承によって促進される抽象化とコードの再利用です。STLは両方を提供します。しかし、Wikipediaの定義を文字どおりに満たすために、STLコンテナー実際に継承を介して実装されています(ただし、これはもちろん実装の詳細です)。
Konrad Rudolph

継承テンプレートの前の主要な機能でした。継承を使用して抽象化を実装することには、テンプレートを使用してその抽象化を実装することほど中心的なことはないと思います。
DeadMG

C ++言語の構文で定義されている方法ではなく、一般的な用語で継承について語る場合、vector <int>は抽象基本クラスvectorから継承されると主張できます。ファンクタと演算子のオーバーロードにより、int型に固有のポリモーフィズムを実現します。

@Lundin True、しかしそれは単にインターフェースの抽象化です。継承もそうです。だから継承を重視しないほうがいいと思います。
Konrad Rudolph

1

私の意見では、STLはオブジェクト指向ではなく、反復可能なコンテナのアルゴリズムに関するものです。

アルゴリズムを使用するために実装される共通インターフェース(イテレーター)を定義します。

C / C ++イテレータはJavaおよびC#では列挙子/列挙可能と呼ばれます

多分STLはOOよりもアスペクト指向です。


1

オブジェクト指向を正当化する仮想メンバー機能を学びました

一体どこで聞いたの?

オブジェクト指向の重要な原則は、カプセル化と抽象化です。virtual関数は、それを実現するための1つの手段にすぎません。実際のオブジェクトの向きにはまったく必要ありません。実際、テンプレートは完全に適切な手段です。それは継承ではないかもしれませんが、それでも一種の多態性です。そして、いくつかのクラスはどちらも必要としません。

標準ライブラリのコンテナは完全にオブジェクト指向です。それらはインターフェースからのすべての不必要な詳細をカプセル化し、実装を合理的に可能な限り最大限に抽象化します。


15年前に "OO"を教えられたとき、3つの重要な柱はカプセル化、継承、および多型であると教えられました。
sbi

継承と多態性は、カプセル化と抽象化という最終目標への1つの手段にすぎません。言うまでもなく、テンプレートは継承を使用しませんが、それらは多態的です。
DeadMG

まあ、sbiが言ったように、それは一般的に教えられています。それは主に赤いニシンだと私はあなたに同意します。
Konrad Rudolph

-1

OOPの実装自体は、「オブジェクト」の意味を定義しない限り、何も意味しません。オブジェクトが値である場合(いわゆるOOP言語のほとんどのようにエンティティではなく、C ++が想定している場合)、STLはOOPであり、それ以外の場合はありません。

次のコードフラグメントを想定します。

Person a("joe");
Person b = a;

同じ生きている人の 2つの表現ですかa、それとも同じ名前の2つの生きているペソンだけですか?b

オブジェクトは何ですか?abまたは彼らが代表する生きている人?

また、C ++の継承は、オブジェクトの継承(抽象化)とは異なる技術的な集約メカニズムです。特定の分野を課す場合、2つは一致する可能性があります(オブジェクトはすべて間接的にアクセス可能であり、すべて置換可能である、つまりすべての関連メソッドが仮想であることを意味します)。そうでない場合、異なる目的をターゲットにすることができます(C ++継承は「暗黙的な構成」にすぎません) )

テンプレートは、(特殊化により)動的タイプ(仮想関数に基づく)ではなく静的タイプに基づく「置換」メカニズムを提供することもできます。この意味で-コンパイル時に同じ専門分野が使用される場合-コンパイル時OOPを提供します。

本質的に、C ++の集計およびディスパッチングスキームは、それ自体がOOPであるか、またはOOPを正当化します。彼らは他のこともできます。OOPは、オブジェクトを一緒に記述および関連付けるための抽象的な方法論です。これらの関係は、オブジェクトタイプがランタイムの実行に依存する場合は継承と仮想ディスパッチにマッピングでき、コンパイル時にオブジェクトタイプを定義できる場合はテンプレートの特殊化と暗黙的な変換にマッピングできます。継承は、参照とポインタ間の暗黙的な変換を提供する方法の1つにすぎません。


継承は、C ++だけでなく、常に集約メカニズムでもあります。
Konrad Rudolph、

私はここで反対投票しなければなりません。仮想メソッドを無視しても、構成には継承との重大な違いがあります。
DeadMG

@KonradRudolph:本当ですが、問題はC ++についてです。
エミリオガラヴァリア2012

@DeadMG:OOP用語以外の「構成」という用語の意味は、平易な英語でも正確な意味があることに注意してください。そして、継承(別の仮想メソッド)は、「名前のないメンバーで構成する」に過ぎません。私はOOP統合主義者がこれらの事実を好まないことを完全に理解していますが、C ++はOOP言語であるだけでなく、継承やクラス構成はOOPの "is a"および "has a"関係を処理するだけではありません。...
エミリオガラヴァリア2012

... OOPの用語とC ++の用語には違いがあります。C ++が継承と仮想メソッド(テンプレートとラムダなし)以外のパラダイムをサポートしていなかった時代には、2つの用語が意図的に混同されて別のものの代わりに使用されていた可能性がありますが、最近ではOOP継承を減らしてOOPを実装するだけにしています置換の原則は、意図的に言語を去勢することです。
エミリオガラヴァリア
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.