私の質問が非常に長く技術的なもので申し訳ありませんが、他の人が興味を持っていることは非常に重要だと思います
一部のソフトウェアの内部構造を C++ での表現から明確に分離する方法を探していました。
boost::any クラスを使用して任意の種類の値を含めることができる汎用パラメーター クラス (後でコンテナーに格納する) があります。
私はこの種の基本クラスを(大まかに)持っています(もちろんもっとあります)
class Parameter
{
public:
Parameter()
template typename<T> T GetValue() const { return any_cast<T>( _value ); }
template typename<T> void SetValue(const T& value) { _value = value; }
string GetValueAsString() const = 0;
void SetValueFromString(const string& str) const = 0;
private:
boost::any _value;
}
派生クラスには 2 つのレベルがあります。最初のレベルでは、型と文字列との間の変換を定義します (たとえば、ParameterInt または ParameterString)。2 番目のレベルでは、動作と実際の作成者を定義します (たとえば、ParameterInt から ParameterAnyInt と ParameterLimitedInt を派生させるか、または ParameterFilename から ParameterFilename を派生させます)。 GenericString)
実際の型に応じて、基本クラスに仮想メソッドを追加せず、奇妙なキャストを行わずに、特定のパラメーターの型に応じて動作する外部関数またはクラスを追加したい
たとえば、パラメーターの種類に応じて適切な GUI コントロールを作成したいと思います。
Widget* CreateWidget(const Parameter& p)
もちろん、RTTI を使用するか、自分で (enum と switch ケースを使用して) 実装しない限り、ここから実際のパラメーターの型を理解することはできませんが、これは正しい OOP 設計ソリューションではありません。
古典的な解決策は、ビジター デザイン パターンhttp://en.wikipedia.org/wiki/Visitor_patternです。
このパターンの問題は、どの派生型が実装されるかを前もって知る必要があることです。そのため (ウィキペディアに書かれているものと私のコードをまとめると)、次のようになります。
struct Visitor
{
virtual void visit(ParameterLimitedInt& wheel) = 0;
virtual void visit(ParameterAnyInt& engine) = 0;
virtual void visit(ParameterFilename& body) = 0;
};
すべての具象型を事前に知る必要がなく、元の訪問者を派生させることなく、他の方法でこの動作を取得する解決策はありますか?
編集: ピザ博士の解決策は私が考えていたものに最も近いようですが、問題は同じであり、メソッドは実際には動的キャストに依存しています。
ビジターパターンを引き合いに出さずに、何らかの解決策を考えて、心をきれいにした方がよいのではないでしょうか。目的は、次のような機能を持つことです。
Widget* CreateWidget(const Parameter& p)
タイプに関する情報を失うことなく、「具体的な」パラメータごとに異なる動作をする