Я создаю класс свойств, который хранит уникальный ключ и произвольное значение в виде строк (плюс необязательную строку комментария для использования при записи в файлы конфигурации). В настоящее время я использую метод создания базового класса свойств, который содержит необработанные строки, а затем делит его на классовые свойства, например. IntProperty, который реализует функцию getValue (), которая преобразует строку в int — чтобы избежать необходимости вручную преобразовывать значение свойства из строки каждый раз, когда я хочу ее прочитать. Эти подклассы используют getPropertyType (), виртуальную функцию, определенную в базе и переопределенную в каждом из производных, чтобы вернуть значение перечисления, чтобы определить, какой тип свойства они содержат, а базовый класс возвращает идентификатор «нет».
(Как примечание, я избегал шаблонов, потому что я использую Qt, и требуемый макрос интерфейса не поддерживает шаблоны объектов. Если стоит использовать шаблоны, я могу отказаться от идеи использования интерфейсов.)
Мое намерение состояло в том, чтобы разрешить списки нескольких различных типов свойств (string, int, float …) путем выделения их подклассов из базового класса свойств и разрешения массивов указателей базовых свойств. Однако я сталкиваюсь с проблемой, заключающейся в том, что становится очень неудобно извлекать свойство как определенный тип из одного из производных классов, поскольку указатель на базовый класс, очевидно, не знает о вновь определенных функциях getValue в производных классах. У меня остается либо опция извлечения строки из базового класса и преобразования вручную, либо приведение указателя базового класса к правильному указателю производного класса. Первая опция делает подклассы бесполезными, требуя, чтобы я выполнял преобразование вручную, а вторая звучит как кошмар для кода, поскольку каждый раз, когда я хочу определить, какой указатель на значение идентификатора свойства, будет задействован большой оператор switch для значения идентификатора свойства. приведение к.
Какой самый разумный способ решить эту проблему? Я хочу, чтобы поиск значений свойств был максимально простым — т.е. иметь как можно меньше стандартного кода, чтобы перейти от получения указателя базового класса из массива к хранению правильно типизированной копии значения свойства. Стоит ли рассматривать проблему с другой стороны — иметь несколько строго типизированных классов свойств, которые поддерживают получение и установку соответствующих значений с помощью строки?
Как насчет этого? (Не проверено, но вы должны понять)
class BaseType {
public:
virtual void getValue(string &s) { s = ""; };
virtual void getValue(int &i) { i = 0; };
virtual void getValue(double &d) { d = 0.0; };
};
class IntType : public BaseType {
public:
virtual void getValue(string &s) { s = to_string(myvalue); };
virtual void getValue(int &i) { i = myvalue; };
virtual void getValue(double &d) { d = static_cast<double>(myvalue); };
private:
int myvalue;
};
class DblType : public BaseType {
public:
virtual void getValue(string &s) { s = to_string(myvalue); };
virtual void getValue(int &i) { i = static_cast<int>myvalue; };
virtual void getValue(double &d) { d = myvalue; };
private:
double myvalue;
};
class StrType : public BaseType {
public:
virtual void getValue(string &s) { s = myvalue; };
virtual void getValue(int &i) { i = stoi(myvalue); };
virtual void getValue(double &d) { d = stod(myvalue); };
private:
string myvalue;
};
Конечно, так как принимающая сторона должна знать, какой тип она получает, используя имя, которое указывает, что вы получаете, например,
int GetInt(const string& key);
string GetString(const string& key);
double GetDouble(const string& key);
и т. д. будет так же хорошо, как назвать его Get(const string& key)
— и поскольку язык C ++ не позволяет вам ТОЛЬКО различать тип возвращаемого значения, это не сработает.
Другая альтернатива, конечно, иметь
template <typename T>
void Get(const string& key, T& value);
(Может потребоваться реализовать разные варианты по-разному, поэтому использование шаблона не очень помогает, но мне гораздо проще написать ответ в качестве шаблона!;))