設定ファイルSettingsController
を管理するクラスがあります。SettingsClient
(1つの純粋仮想関数、メンバーなし)を登録することができます。関連する設定エントリが更新されるように変更されたときには、SettingsClient
に通知されます。継承と組み合わせてObserverパターンを実現するにはどうすればよいですか?
今、私はいくつかの設定項目を必要とするため、SettingsClient
とレジスタSettingsController
でも、いくつかの設定項目を必要とし、コントローラでクライアントとレジスタを継承し、具体的なリポジトリConcreteRepository
を継承RepositoryBase
を持っています。
ConcreteRepository
はRepositoryBase
を継承し、両方が(JavaでConcreteRepository
はRepositoryBase
をextend
なり、両方がSettingsClient
をimplement
なる)コントローラに登録することができるようにSettingsClient
を継承します。
私の問題は次のとおりです。コンパイラはあいまいであるため、これをしないよう警告します。残念ながら仮想継承は、ConcreteRepository
またはRepositoryBase
の実装された関数を上書きし、2つのクラスのうちの1つのリフレッシュ機能を無効にするため、ここでは役に立ちません。
この継承とオブザーバーの組み合わせを実現する方法はありますか?私は、これはConcreteRepository
のメンバーに設計上の欠陥とRepositoryBase
ニーズかもしれません考えています
をここで概要を与えるためにいくつかのコードである(?):
#include <vector>
#include <iostream>
class SettingsClient {
public:
virtual void reloadSettings() = 0;
};
class SettingsController {
void notify(){
for(SettingsClient* client : clients){
client->reloadSettings(); // error! reloadSettings() of RepositoryBase or ConcreteRepository?
}
}
void registerClient(SettingsClient *client) {
clients.push_back(client);
}
std::vector<SettingsClient*> clients;
};
class RepositoryBase : private SettingsClient {
// ...
virtual void reloadSettings() {
std::cout << "Reloading Base!" << "\n";
}
// ...
};
class ConcreteRepository : private SettingsClient, private RepositoryBase {
// ...
virtual void reloadSettings() {
std::cout << "Reloading ConcreteRepository!" << "\n";
}
// ...
};
公開されているので、SettingsClientは仮想デストラクターが必要です。ConcreteRepositoryは、RepositoryBase経由で既に設定されているため、SettingsClientを継承する必要はありません。必要に応じてRepositoryBaseのreloadSettingsを明示的に呼び出します。 C++には、オーバーライドされたメンバーを複数の基本クラスを呼び出すようにデフォルトするメカニズムはありません。 – evan