2013-07-03 2 views
2

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

(В качестве примечания, я уклонялся от шаблонов, потому что я использую 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; 
}; 
+0

Это хороший способ сделать это. В конце концов я решил пойти с методом посетителя, где передача объекта-посетителя указателю базового класса вернет его с данными как правильный тип, содержащийся внутри посетителя. – x6herbius

0

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

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

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