Ответ 1
Одним из вариантов может быть использование шаблона посетителя. Вы можете создать базовый класс следующим образом:
class Parameter {
public:
virtual ~Parameter() {} // Polymorphic classes need virtual dtors.
virtual void accept(ParameterVisitor& v) = 0;
};
Вы можете определить такие подклассы, как эти:
class IntParameter: public Parameter {
public:
virtual void accept(ParameterVisitor& v) {
v.visit(*this);
}
};
class FilenameParameter: public Parameter {
public:
virtual void accept(ParameterVisitor& v) {
v.visit(*this);
}
};
Обратите внимание, что в каждой функции-члена accept
тип *this
является статическим типом класса, а именно, IntParameter&
в первом случае, а FilenameParameter&
во втором случае.
Затем вы можете определить класс базового класса ParameterVisitor
следующим образом:
class ParameterVisitor {
public:
virtual ~ParameterVisitor() {} // Polymorphic classes need virtual dtors.
virtual void visit(IntParameter& p) {}
virtual void visit(FilenameParameter& p) {}
/* .. etc. .. */
};
Затем вы можете подклассифицировать этого посетителя, чтобы получить информацию о типе:
class Gui1ParameterVisitor: public ParameterVisitor {
public:
virtual void visit(IntParameter& p) {
/* ... use GUI1 to create a field for an integer. */
}
virtual void visit(FilenameParameter& p) {
/* ... use GUI1 to create a field for a filename. */
}
};
class Gui2ParameterVisitor: public ParameterVisitor {
public:
virtual void visit(IntParameter& p) {
/* ... use GUI2 to create a field for an integer. */
}
virtual void visit(FilenameParameter& p) {
/* ... use GUI2 to create a field for a filename. */
}
};
Затем ваш класс ParameterList
может просто сохранить список Parameter*
s. Затем вы можете создать графический интерфейс, создав соответствующий тип посетителя, а затем получив обратные вызовы visit
, выполнив всю конструкцию виджета. Это заканчивается безопасностью типа и восстанавливает необходимую вам информацию. У этого есть недостаток: каждый раз, когда вы создаете новый тип параметра, вам нужно добавить новую функцию-член visit
в класс ParameterVisitor
, но вам все равно нужно сделать все это для создания графического интерфейса.
Надеюсь, это поможет!