[解決済み] クラス階層に対してoperator==をオーバーロードする正しい方法は何ですか?
質問
次のようなクラス階層があるとします。
class A
{
int foo;
virtual ~A() = 0;
};
A::~A() {}
class B : public A
{
int bar;
};
class C : public A
{
int baz;
};
をオーバーロードする正しい方法は何ですか?
operator==
は、これらのクラスのために? もし、これらをすべてフリー関数にすると、BとCはキャストしないとAのバージョンを活用できない。 また、Aへの参照だけを持っている人が深い比較をすることもできなくなります。
bool B::operator==(const A& rhs) const
{
const B* ptr = dynamic_cast<const B*>(&rhs);
if (ptr != 0) {
return (bar == ptr->bar) && (A::operator==(*this, rhs));
}
else {
return false;
}
}
今回もやはりキャストしなければなりません(間違っているような気がします)。 何か好ましい方法はないでしょうか?
更新してください。
今のところ回答は2つしかありませんが、正しい方法は代入演算子と類似しているようです。
- リーフ以外のクラスを抽象化する
- 非リーフクラスでの非仮想の保護
- リーフクラスにおけるパブリック非仮想
基本関数は保護されており、リーフクラスは親のバージョンを利用してデータのその部分を比較できるため、異なる型の2つのオブジェクトをユーザーが比較しようとすると、コンパイルされないでしょう。
どうやって解決するの?
このような階層構造では、Scott MeyerのEffective C++のアドバイスに従って、具体的な基底クラスを持たないようにするのが間違いないでしょう。いずれにせよ、あなたはこれを実行しているように見えます。
私なら
operator==
を、具体的なリーフ・ノード・クラスのタイプに対してのみ、自由な関数として、おそらくは友人として、提供します。
もしベースクラスがデータメンバーを持たなければならないのであれば、ベースクラス内に(おそらく保護された)非仮想ヘルパー関数を提供します (
isEqual
というように)、派生クラスの
operator==
を使用することができます。
例
bool operator==(const B& lhs, const B& rhs)
{
return lhs.isEqual( rhs ) && lhs.bar == rhs.bar;
}
を持たないようにすることで
operator==
抽象的な基底クラスで動作する比較関数を保護したままにしておけば、型が異なる2つのオブジェクトの基底部分のみを比較するようなフォールバックをクライアントコードで誤って行うことはありません。
仮想比較関数を実装する際に
dynamic_cast
しかし、もしその必要性が証明されているのであれば、私はおそらくベースクラスの純粋な仮想関数にするでしょう (
ではなく
operator==
) を使って、具体的な派生クラスで次のようにオーバーライドされました。
operator==
を派生クラスに追加しました。
bool B::pubIsEqual( const A& rhs ) const
{
const B* b = dynamic_cast< const B* >( &rhs );
return b != NULL && *this == *b;
}
関連
-
[解決済み】getline()が何らかの入力の後に使用されると動作しない 【重複あり
-
[解決済み】Visual Studio 2015で「非標準の構文。'&'を使用してメンバーへのポインターを作成します」エラー
-
[解決済み】C++でユーザー入力を待つ【重複あり
-
[解決済み】C++エラーです。"配列は中括弧で囲まれたイニシャライザーで初期化する必要がある"
-
[解決済み] 式はクラス型を持つ必要があります。
-
[解決済み】 while(cin) と while(cin >> num) の違いは何ですか?)
-
[解決済み】警告 - 符号付き整数式と符号なし整数式の比較
-
[解決済み] ベースクラスのコンストラクタを呼び出す際のルールは?
-
[解決済み】C/C++の"-->"演算子とは何ですか?
-
[解決済み】 ostreamの<<演算子を適切にオーバーロードする方法は?
最新
-
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 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】getline()が何らかの入力の後に使用されると動作しない 【重複あり
-
[解決済み] エラーが発生する。ISO C++は型を持たない宣言を禁じています。
-
[解決済み】「corrupted size vs. prev_size」glibc エラーを理解する。
-
[解決済み】C++の変数はイニシャライザーを持っているが、不完全な型?
-
[解決済み】浮動小数点例外エラーが発生する: 8
-
[解決済み】c++でstd::vectorを返すための効率的な方法
-
[解決済み】Visual C++で "Debug Assertion failed "の原因となる行を見つける。
-
[解決済み】浮動小数点数の乱数生成
-
[解決済み】'std::cout'への未定義の参照
-
[解決済み】エラー。引数リストに一致するコンストラクタのインスタンスがない