很抱歉,如果我的问题如此冗长且技术性很强,但我认为其他人会对它感兴趣很重要
我正在寻找一种方法来清楚地将一些软件内部与它们在 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;
}
派生类有两个级别:第一级定义类型和与字符串的转换(例如 ParameterInt 或 ParameterString) 第二级定义行为和真正的创建者(例如从 ParameterInt 或 ParameterFilename 派生 ParameterAnyInt 和 ParameterLimitedInt通用字符串)
根据实际类型,我想添加外部函数或根据特定参数类型运行的类,而不向基类添加虚拟方法并且不进行奇怪的强制转换
例如,我想根据参数类型创建适当的 gui 控件:
Widget* CreateWidget(const Parameter& p)
当然,除非我使用 RTTI 或我自己实现它(使用枚举和 switch case),否则我无法从中理解真正的参数类型,但这不是正确的 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;
};
是否有任何解决方案可以以任何其他方式获得此行为,而无需事先知道所有具体类型并且无需派生原始访问者?
编辑: Pizza 博士的解决方案似乎最接近我的想法,但问题仍然存在,并且该方法实际上依赖于 dynamic_cast,我试图将其作为一种(即使很弱)RTTI 方法来避免
也许最好在不引用访问者模式的情况下思考一些解决方案并清理我们的思想。目的只是具有以下功能:
Widget* CreateWidget(const Parameter& p)
每个“具体”参数的行为不同,而不会丢失其类型的信息