параметрический полиморфизм — полиморфные функции C ++ с различными типами возвращаемых значений

Я создаю класс свойств, который хранит уникальный ключ и произвольное значение в виде строк (плюс необязательную строку комментария для использования при записи в файлы конфигурации). В настоящее время я использую метод создания базового класса свойств, который содержит необработанные строки, а затем делит его на классовые свойства, например. IntProperty, который реализует функцию getValue (), которая преобразует строку в int — чтобы избежать необходимости вручную преобразовывать значение свойства из строки каждый раз, когда я хочу ее прочитать. Эти подклассы используют getPropertyType (), виртуальную функцию, определенную в базе и переопределенную в каждом из производных, чтобы вернуть значение перечисления, чтобы определить, какой тип свойства они содержат, а базовый класс возвращает идентификатор «нет».

(Как примечание, я избегал шаблонов, потому что я использую Qt, и требуемый макрос интерфейса не поддерживает шаблоны объектов. Если стоит использовать шаблоны, я могу отказаться от идеи использования интерфейсов.)

Мое намерение состояло в том, чтобы разрешить списки нескольких различных типов свойств (string, int, float …) путем выделения их подклассов из базового класса свойств и разрешения массивов указателей базовых свойств. Однако я сталкиваюсь с проблемой, заключающейся в том, что становится очень неудобно извлекать свойство как определенный тип из одного из производных классов, поскольку указатель на базовый класс, очевидно, не знает о вновь определенных функциях getValue в производных классах. У меня остается либо опция извлечения строки из базового класса и преобразования вручную, либо приведение указателя базового класса к правильному указателю производного класса. Первая опция делает подклассы бесполезными, требуя, чтобы я выполнял преобразование вручную, а вторая звучит как кошмар для кода, поскольку каждый раз, когда я хочу определить, какой указатель на значение идентификатора свойства, будет задействован большой оператор switch для значения идентификатора свойства. приведение к.

Какой самый разумный способ решить эту проблему? Я хочу, чтобы поиск значений свойств был максимально простым — т.е. иметь как можно меньше стандартного кода, чтобы перейти от получения указателя базового класса из массива к хранению правильно типизированной копии значения свойства. Стоит ли рассматривать проблему с другой стороны — иметь несколько строго типизированных классов свойств, которые поддерживают получение и установку соответствующих значений с помощью строки?

2

Решение

Как насчет этого? (Не проверено, но вы должны понять)

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;
};
2

Другие решения

Конечно, так как принимающая сторона должна знать, какой тип она получает, используя имя, которое указывает, что вы получаете, например,

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);

(Может потребоваться реализовать разные варианты по-разному, поэтому использование шаблона не очень помогает, но мне гораздо проще написать ответ в качестве шаблона!;))

0

По вопросам рекламы [email protected]