好奇心から:オブジェクトをインスタンス化する方法として、a = new A
代わりにC++ を選択するのはなぜですか? a = A.new
後者の方がオブジェクト指向に似ていませんか?
8 に答える
好奇心から:オブジェクトをインスタンス化する方法として、C++がa=A.newではなくa= new Aを選択するのはなぜですか?後者はよりオブジェクト指向のように見えませんか?
しますか?それは、「オブジェクト指向」をどのように定義するかによって異なります。
これを定義すると、Javaのように、「すべてが「X.Y
」という形式の構文を持っている必要があります。ここX
で、はオブジェクトであり、Y
そのオブジェクトでやりたいことは何でもあります。そうです、そうです。これは正しくありません。オブジェクト指向であり、JavaはOOPプログラミングの頂点です。
しかし、幸いなことに、「オブジェクト指向」は、オブジェクトで使用されている構文ではなく、オブジェクトの動作に関連している必要があると考える人もいます。基本的には、ウィキペディアのページにあるように要約する必要があります。
オブジェクト指向プログラミングは、「オブジェクト」(データフィールドとメソッド、およびそれらの相互作用で構成されるデータ構造)を使用して、アプリケーションとコンピュータープログラムを設計するプログラミングパラダイムです。プログラミング手法には、情報隠蔽、データ抽象化、カプセル化、モジュール性、ポリモーフィズム、継承などの機能が含まれる場合があります。
構文については何も述べていないことに注意してください。「オブジェクト名、ドット、関数名の順に指定して、すべての関数を呼び出す必要があります」とは書かれていません。
そして、その定義を考えると、foo(x)
はオブジェクト指向とまったく同じx.foo()
です。重要なのは、それx
がオブジェクトであるということです。つまり、データフィールドと、それを操作できる一連のメソッドで構成されています。この場合、foo
は、それがどこで定義されているかに関係なく、またそれを呼び出す際にどの構文が使用されているかに関係なく、明らかにそれらのメソッドの1つです。
C ++の達人はこれをずっと前に認識しており、このような記事を書いています。オブジェクトのインターフェースは、メンバーメソッドのセット(ドット構文で呼び出すことができます)だけではありません。オブジェクトを操作できる関数のセットです。彼らがメンバーであるか友人であるかは、実際には重要ではありません。オブジェクトが一貫性を保つことができる限り、つまり、任意の関数がオブジェクトを混乱させるのを防ぐことができる限り、オブジェクト指向です。
では、なぜA.new
もっとオブジェクト指向になるのでしょうか?このフォームはどのようにして「より良い」オブジェクトを提供しますか?
OOPの背後にある重要な目標の1つは、より再利用可能なコードを許可することでした。
すべてのクラスのメンバーであった場合new
、それはすべてのクラスが独自の new
操作を定義する必要があることを意味します。非メンバーの場合、すべてのクラスが同じクラスを再利用できます。機能は同じなので(メモリの割り当て、コンストラクターの呼び出し)、すべてのクラスが再利用できるオープンに配置してみませんか?(プリエンプティブな落とし穴:もちろん、new
この場合も、共通の基本クラスから継承するか、コンパイラの魔法を少しかけることで、同じ実装を再利用できます。しかし、最終的には、メカニズムを配置できるのに、なぜわざわざするのでしょうか。そもそもクラス外)
C ++ではメンバーアクセスにのみ使用されるため、ドットの.
右側は常にオブジェクトであり、タイプではありません。どちらかといえば、よりも論理的A::new()
ですA.new()
。
いずれの場合も、動的オブジェクト割り当ては特別です。コンパイラはメモリを割り当て、2つのステップでオブジェクトを構築し、いずれかのステップで例外を処理するコードを追加して、メモリがリークされないようにします。特別な操作ではなくメンバー関数呼び出しのように見せることは、操作の特別な性質を曖昧にするものと見なすことができます。
ここでの最大の混乱は、 newには2つの意味があることだと思います。組み込みのnew-expression(メモリ割り当てとオブジェクト作成を組み合わせたもの)と、オーバーロード可能な演算子new(メモリ割り当てのみを処理する)があります。1つ目は、私が見る限り、動作を変更できないものであるため、メンバー関数になりすますことは意味がありません。(または、クラスが実装/オーバーライドできないメンバー関数であるか、そのように見える必要があります!!)
これはまた別の矛盾につながるでしょう:
int* p = int.new;
C ++は、すべてがオブジェクトであるとは限らないという点で、純粋なOOP言語ではありません。
C ++では、無料の関数(一部の作成者と、SC ++ L設計で設定された例によって推奨されています)を使用することもできます。これは、C++プログラマーが慣れているはずです。もちろん、new-expressionは関数ではありませんが、free-function呼び出しを漠然と思い出させる構文が、free-function呼び出しが非常に一般的な言語でだれをも先延ばしにすることができるかどうかはわかりません。
コードを読んでください(動作します)。そうすれば、さまざまなアイデアが得られます。
CObject *p = (CObject*)malloc(sizeof *p);
...
p = new(p) CObject;
p->DoSomthing();
...
A.new
A
whilea = new A
はメモリを割り当て、後でオブジェクトのコンストラクタを呼び出す静的関数です。
実際にはA.new
、適切なメソッドを追加すれば、のようなものでオブジェクトをインスタンス化できます。
class A{
public: static A* instance()
{ return new A(); }
};
A *a = A::instance();
しかし、そうではありません。構文もそうではありません。右側を調べること::
で、 「操作」を区別できます。.
その理由はメモリ管理だと思います。C ++では、他の多くのオブジェクト指向言語とは異なり、メモリ管理はユーザーによって行われます。デフォルトのガベージコレクターはありませんが、標準ライブラリと非標準ライブラリには、メモリを管理するためのさまざまな手法とともにガベージコレクターが含まれています。したがって、プログラマーは、メモリー割り当てがここに含まれていることを理解するためにオペレーターを確認する必要があります。new
オーバーロードされていない限り、new
演算子を使用すると、最初にrawメモリが割り当てられ、次に、割り当てられたメモリ内にそれを構築するオブジェクトコンストラクタが呼び出されます。ここでは「生の」低レベルの操作が含まれるため、クラスメソッドの1つではなく、別個の言語演算子である必要があります。
理由はないと思います。そのa=new aは、最初にそのようにドラフトされたからです。後から考えると、おそらくa = a.new();であるはずです。
なぜ各クラスの新しいものを別々にする必要があるのですか?
newの目的は、適切なメモリを割り当て、コンストラクタを呼び出してオブジェクトを構築することであるため、これが必要だとはまったく思いません。したがって、newの動作は、クラスに関係なく、一意で独立しています。では、なぜ作らないのが再利用可能なのですか?
自分でメモリ管理を行いたい場合(つまり、メモリプールを1回割り当てて、オンデマンドでメモリを返すことにより)、newをオーバーライドできます。