インターフェイスとして機能する抽象基本クラスがあります。
抽象クラスの半分を実装する派生クラスの 2 つの「セット」があります。(一方の「セット」は初期化に関連する抽象仮想メソッドを定義し、もう一方の「セット」は実際の「作業」に関連するメソッドを定義します。)
次に、複数の継承を使用して完全に定義されたクラスを構築する派生クラスを作成します (それ自体は何も追加しません)。
だから:(悪い疑似コード)
class AbsBase {
virtual void init() = 0;
virtual void work() = 0;
}
class AbsInit : public AbsBase {
void init() { do_this(); }
// work() still abs
}
class AbsWork : public AbsBase {
void work() { do_this(); }
// init() still abs
}
class NotAbsTotal : public AbsInit, public AbsWork {
// Nothing, both should be defined
}
まず、これでいいの?同じ Base から派生した 2 つのクラスを継承できますか? (そうだといい)。
ただし、これが「本当の問題」です(例を単純化するために少し上に嘘をつきました)。
私が実際に行ったことは、非抽象アクセサー メソッドを基本クラスに追加することです。
class AbsBase {
public:
void init() { init_impl(); }
void work() { work_impl(); }
private:
virtual void init_impl() = 0;
virtual void work_impl() = 0;
}
一般的なイディオムは、すべての仮想メソッドを非公開にすることです。
残念ながら、現在、AbsInit と AbsWork の両方がこれらのメソッドを継承しているため、NotAbsTotal は「それぞれ 2 つ」を継承しています (コンパイル時に実際に起こっていることを解体している可能性があることに気付きました)。
とにかく、g ++は、クラスを使用しようとすると「メンバーinit()のリクエストがあいまいです」と不平を言います。
AbsBase クラスを純粋なインターフェイスとして使用していれば、これは回避できたと思います (上の例が有効であると仮定します)。
だから: - 私は私の実装から離れていますか?- これは、仮想メソッドを非公開にするイディオムの制限ですか? - コードをリファクタリングして、やりたいことを実行するにはどうすればよいですか? (1 つの共通インターフェースを提供しますが、メンバー関数の「セット」の実装を交換する方法を許可します)
編集:
私は最初のものではないようです: http://en.wikipedia.org/wiki/Diamond_problem
ここでは仮想継承が解決策のようです。以前に仮想継承について聞いたことがありますが、それについて頭を悩ませたことはありません。私はまだ提案を受け付けています。