問題タブ [virtual-inheritance]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
c++ - C++: オーバーロードされた非仮想メソッドと仮想メソッドの両方を同じ名前で継承すると問題が発生する
パラメーター リストが異なる 2 つの同じ名前のメソッドを派生クラスに継承しようとしています。そのうちの 1 つは仮想であり、派生クラスでオーバーライドされます。もう 1 つは非仮想です。そうすると、派生クラス オブジェクトから基底クラスの非仮想メソッドにアクセスしようとすると、コンパイル エラーが発生します。
ここにコードスニペットがあります
次のコンパイル エラーが発生します。
エラー: 'Deriv::f()' の呼び出しに一致する関数がありません<br /> 注: 候補は: virtual void Deriv::f(int)
私は C++ の専門家ではありませんが、これまでは、メンバー メソッドはシグネチャによって完全に区別できるという仮定が正しいと考えていました。したがって、非仮想メソッド Base::f() をオーバーライドしてはならず、アクセス可能なままにしておく必要があります。私はこれで間違っていますか?
これに関する興味深い/追加のコメントを次に示します。
- - オーバーライド メソッド Deriv::f(int arg) も非仮想である可能性があります。エラーはどちらの方法でも発生します
-エラーは消えます/回避できます...
- ... Deriv オブジェクトを Base クラスにキャストすることにより ... Deriv で
Base::f(int arg) をオーバーライドしない場合
... コマンド「Base::f;」を追加することにより Derivの公開部分へ
このコンパイル エラーを回避する方法は既に知っているので、主にこのエラーが発生する理由に関心があります。
c++ - 複雑な多重継承階層で必要な「仮想」キーワードはどこにありますか?
C++ の仮想継承の基本を理解しています。virtual
ただし、複雑なクラス階層でキーワードを使用する必要がある正確な場所については混乱しています。たとえば、次のクラスがあるとします。
どのクラスもどのサブクラスにも複数回出現しないようにしたい場合、どの基本クラスをマークする必要がありvirtual
ますか? それらのすべて?または、そうでなければ複数のインスタンスを持つ可能性のあるクラスから直接派生するクラス (つまり、B、C、D、E、F、および G と H) でのみ使用するだけで十分ですか?基本クラス D および F))?
c++ - 基本クラスのリストは、仮想継承を示す適切な場所ですか?
クラスが仮想および非仮想ベースとして使用されているのを見たことがありません (つまり、一部のクラスが先祖になることを意図している場合、通常、継承のタイプ (仮想または非仮想) について事前にわかっています)。
したがって、C++には、基本クラスリストで「仮想」継承を特殊化するためのエラーが発生しやすい自由があると思います。基本クラス自体を「仮想」として指定する方が良いはずです
それとも私が間違っているのでしょうか?
いいえの場合、そのような「仮想」クラスの偶発的な非仮想継承を防ぐためのテクニックを誰かが説明できますか?
それとも、今後の C++ 標準にいくつかの展望がありますか?
(重複していたらごめんなさい)
いくつかの例
1) 一部の参照カウントベースのスマートポインターが指すことができるすべてのクラスのベースとしての ReferenceCounted クラス。この基本インスタンス (および参照カウンター) の重複を防ぐ必要があります。最適化を除いて、このクラスを非仮想ベースとして使用する理由はありません。
2) インターフェースの階層と対応する実装の階層 (この場合、インターフェースの階層は「仮想」でなければなりません)
多くの場合、非仮想継承は概念的な必要性ではなく、仮想継承のオーバーヘッドを削減するためだけに使用されていると思います (時には static_cast<> を駆動する機能のために:)
Javaはインターフェイスに仮想(c ++に関して)継承のみを使用したことに注意してください。この言語には「非仮想」がないという不満はありません(本質的にC ++よりも表現力の低い言語ですが、この「機能」はメインではありません障害 :)。
c++ - 仮想基本クラスのオーバーロードされたコンストラクターの呼び出し
通常の (仮想) コンストラクターの呼び出し順序をバイパスする (実用的な) 方法はありますか?
例:
出力:
A( int) の
呼び出し B(int)の
呼び出し C(int)の
呼び出し D(int ) の呼び出し
私がしたいのは次のようなものです:
A(int) の
呼び出し B(int)の
呼び出し C(int)の
呼び出し D(int ) の呼び出し
ご覧のとおり、仮想継承が関係しているため、D のコンストラクターは最初に A のコンストラクターを呼び出しますが、パラメーターが指定されていないため、A() を呼び出します。初期化が必要なconst int i があるので、問題があります。
私がやりたいのは、C の継承の詳細を非表示にすることです。そのため、D (およびすべての派生) コンストラクターの初期化リストで A(i) を呼び出さないようにする方法を探しています。[編集] この特定のケースでは、C の非仮想単一継承の子クラスしかないと仮定できます (D は 1 つなので)。[/編集]
[編集]
仮想基本クラスは、非仮想基本クラスが初期化される前に初期化されるため、最も派生したクラスのみが仮想基本クラスを初期化できます。– ジェームズ・マクネリス
それがまさにポイントです。最も派生したクラスが仮想基本クラスのコンストラクターを呼び出す ことは望ましくありません。[/編集]
次の状況を考えてみましょう (上記のコード例には示されていません)。
C をインスタンス化するときに C が A の ctor を呼び出さなければならない理由 (あいまいさ) は理解できますが、D をインスタンス化するときに D がそれを呼び出さなければならないのはなぜですか?
c++ - C++ は、仮想ベース A を介してベース A から派生型 B に変換できません
私は3つのクラスを持っています:
A* から B* への静的キャストを試行すると、次のエラーが発生します。
c++ - C++仮想継承と型キャスト/コピーコンストラクターの混乱
私は以下のコードを持っています:
驚いたことに、B(const A&a)は呼び出されません。何故ですか?
c++ - 仮想継承と仲間の MSVC9.0 バグまたは誤解?
次のコードを検討してください。
MSVC9.0 (Visual Studio 2008 の C++ コンパイラ) は既定のコンストラクターを生成しますが、C は A の仲間ですが、C のコピーおよび代入演算子を生成できません。これは予想される動作ですか、それとも Microsoft のバグですか? 後者の場合だと思います。私が正しければ、この問題が議論されている記事/フォーラム/...、またはマイクロソフトがこのバグに対応している場所を誰かが指摘できます。前もって感謝します。
PS ちなみに、両方のプライベート継承が保護に変更された場合、すべてが機能します
PPS 上記のコードが合法か違法かの証明が必要です。私が理解しているように、仮想プライベートベースを持つクラスは派生できないことが実際に意図されていました。しかし、彼らは友達の部分を見逃しているようです. だから...これが私の最初の報奨金です:)
c++ - 仮想継承は静的構成を壊しませんか?
私は過去5年間、仮想継承が静的構成を破壊することを想定して作業していました。
しかし、静的な構成がまだ維持されていることを発見しました。正しいインスタンスの場所に関する追加情報があります。これは正しいですか?
c++ - 仮想基底クラスの代入演算子が 1 回だけ呼び出されるようにするにはどうすればよいですか?
典型的なダイヤモンドの問題のように、仮想継承を使用しています。
すべてのクラスに「deep_copy_from」という名前のメソッドを実装しています (ただし、代入 operator=() の場合もあります)。このメソッドは、クラス独自の属性をコピーし、そのコピーを上のクラスに伝達する必要があります。
問題は、D インスタンスをディープ コピーしているときに A::deep_copy_from メソッドが 2 回呼び出されることです (A の「バージョン」は 1 つしかないため、1 回だけ呼び出す必要があります)。一度だけ呼び出されるようにする最善の方法は何ですか?
(B::deep_copy_from と C::deep_copy_from は引き続き同じように動作するはずです)。
サンプルコードは次のとおりです。
現在の出力は次のとおりです。
アップデート:
現在のバージョンは次のとおりです。
出力は次のとおりです。
それよりも良いものを手に入れることはできますか?(つまり、より自動化された)
c++ - 「最派生クラスの ctor は、仮想基底クラスの ctor を直接呼び出す必要がある」という文の元はどこですか?
C++ で final クラスを実装する方法を学習しているときに、次のようなステートメントを見つけました。
「最も派生したクラスの ctor は、仮想基本クラスの ctor を直接呼び出す必要があります。」
ただし、C++ 標準のステートメントの元が見つかりません。(N3126)
正確なページ番号を誰が教えてくれますか?
前もって感謝します。