なぜポインタ/参照がないとポリモーフィズムは機能しないのか?
疑問点
SOで似たようなタイトルの質問をいくつか見つけましたが、回答を読むと、質問の異なる部分に焦点を合わせていて、本当に具体的でした (例: STL/コンテナ)。
なぜポリモーフィズムを実装するためにポインタや参照を使用しなければならないのか、どなたか教えていただけませんか?私はポインタが役立つかもしれないことを理解できますが、確かに参照は値渡しと参照渡しを区別するだけでしょうか?
確かに、ヒープ上にメモリを確保し、動的バインディングができるようにすれば、それで十分だったのでしょうが、明らかにそうではありません。
どのように解決するのですか?
C++では、オブジェクトは常にコンパイル時に既知の固定型とサイズを持ち、(アドレスを取得することが可能である場合) その寿命の間、常に固定アドレスに存在します。これらはC言語から受け継いだ機能であり、両言語を低レベルのシステムプログラミングに適したものにするのに役立っている。(これらはすべて as-if のルールに従いますが、規格に準拠したコンパイラーは、規格によって保証された準拠プログラムの動作に検出可能な影響を与えないことが証明できる限り、コードに対して自由に好きなことを行うことができます)。
A
virtual
関数は、オブジェクトの実行時型に基づいて実行されると定義されています(多かれ少なかれ、極端な言語処理は必要ありません)。
virtual
関数がこの方法で呼び出された場合、ポリモーフィズムはありません。
これは必ずしもそうである必要はなかったことに注意してください:オブジェクト型に
virtual
関数を持つオブジェクト型は、通常 C++ で実装され、オブジェクトごとのポインタが
virtual
関数のテーブルへのオブジェクトごとのポインタを使用して実装されます。もしその気になれば、C++ のある仮想的な変種のコンパイラは、オブジェクトへの代入(たとえば
Base b; b = Derived()
のような) オブジェクトへの代入を、オブジェクトのコンテンツと
virtual
テーブルポインタの両方をコピーするものとして扱われます。
Base
と
Derived
が同じサイズであった場合。2 つが同じサイズでない場合、コンパイラーは、プログラム内のメモリを再配置し、プログラムのセマンティクスに検出可能な影響を与えないことが証明できる方法でそのメモリへのすべての可能な参照を更新するために、任意の時間、プログラムを一時停止するコードを挿入し、そのような再配置が見つからなかった場合にプログラムを終了することもできます。
そのため、上記の代わりに、C++ における多相性は、オブジェクトへの参照とポインタが、宣言されたコンパイル時の型とその任意のサブタイプのオブジェクトを参照およびポイントできるようにすることで実現されています。このとき
virtual
関数が参照やポインタを通して呼び出され、参照または指されたオブジェクトがその
virtual
関数が呼び出された場合、コンパイラは正しい
virtual
関数を呼び出すコードを挿入します。参照やポインタをポリモーフィックでないと定義し(宣言された型のサブタイプを参照したり指し示したりすることを禁止し)、プログラマにポリモーフィズムを実装する別の方法を考えさせることも可能でした。後者は C 言語で常に行われているので明らかに可能ですが、その時点では新しい言語を持つ理由はあまりありません。
まとめると、C++のセマンティクスは、オブジェクト指向ポリモーフィズムの高レベルな抽象化とカプセル化を可能にする一方で、低レベルな開発に適した機能(低レベルなアクセスやメモリの明示的な管理など)を保持するように設計されているのです。他のセマンティクスを持つ言語を設計することは容易ですが、それはC++ではなく、異なる利点と欠点を持つことになるでしょう。
関連
-
[解決済み】C++ クラスヘッダが含まれているときに「不明な型」があるのはなぜですか?重複
-
[解決済み】システムが指定されたファイルを見つけられませんでした。
-
[解決済み】CMakeエラー at CMakeLists.txt:30 (project)。CMAKE_C_COMPILER が見つかりませんでした。
-
[解決済み】クラスのコンストラクタへの未定義参照、.cppファイルの修正も含む
-
[解決済み】 while(cin) と while(cin >> num) の違いは何ですか?)
-
[解決済み】システムが指定されたファイルを見つけられませんでした。
-
[解決済み] リファレンスとポインタの使い分け
-
[解決済み】なぜダブルインダイレクトを使うのか、なぜポインターをポインターにするのか?
-
[解決済み] C++におけるポインタへの参照の渡し方
-
[解決済み] なぜrefとoutはポリモーフィズムをサポートしないのですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] テスト
-
[解決済み】抽象クラス型の無効なnew-expression
-
[解決済み] error: 'if' の前に unqualified-id を期待した。
-
[解決済み】デバッグアサーションに失敗しました。C++のベクトル添え字が範囲外
-
[解決済み】エラー:free(): 次のサイズが無効です(fast)。
-
[解決済み】CMakeエラー at CMakeLists.txt:30 (project)。CMAKE_C_COMPILER が見つかりませんでした。
-
[解決済み】クラスのコンストラクタへの未定義参照、.cppファイルの修正も含む
-
[解決済み] to_string は std のメンバーではない、と g++ が言っている (mingw)
-
[解決済み】デバッグアサーションに失敗しました
-
[解決済み】エラー。引数リストに一致するコンストラクタのインスタンスがない