문제

I am creating a property class which stores a unique key and an arbitrary value as strings (plus an optional comment string for use when writing to configuration files). Currently I'm using the method of creating a base property class which holds the raw strings, and then subclassing this into type-specific properties - eg. an IntProperty which implements a getValue() function that converts the string to an int - to avoid having to convert a property value manually from a string every time I want to read it. These subclasses use getPropertyType(), a virtual function defined in the base and overridden in each of the derived, to return an enum value to identify which type of property they hold, and the base class returns a "none" identifier.

(As a side note, I shied away from templates because I'm using Qt and its required interface macro doesn't support templated objects. If it's worth using templates I may ditch the idea of using interfaces.)

My intention was to allow for lists of multiple different types of properties (string, int, float...) by subclassing them from the base property class and allowing arrays of base property pointers. However, I run into the problem that it then becomes very awkward to extract the property as a specific type from one of the derived classes, since the pointer to the base class obviously does not know about the newly defined getValue functions in the derived classes. I am left with either the option of extracting the string from the base class and converting manually or by casting the base class pointer to the correct derived class pointer. The first option renders the subclassing useless by requiring that I do the conversion manually, and the second sounds like a nightmare to code since there'll be a large switch statement involved on the property identifier value each time I want to work out which pointer to cast to.

What would be the most intelligent way of going about this problem? I want to keep the retrieval of property values as simple as possible - ie. have as little boilerplate code as I can to go from getting a base class pointer from an array to holding a properly typed copy of the property's value. Would it be worth considering the problem the other way around - have multiple strongly-typed property classes which all support getting and setting their respective value using a string?

도움이 되었습니까?

해결책

What about this? (Untested, but you should get the idea)

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

다른 팁

Surely, since the receiving side needs to know what type it's getting, using a name that indicates what you get back, e.g.

int GetInt(const string& key);
string GetString(const string& key);
double GetDouble(const string& key); 

etc. would be just as good as calling it Get(const string& key) - and since the C++ language doesn't allow you to ONLY differentiate on the return type, that wouldn't work.

Another alternative is of course to have a

template <typename T>
void Get(const string& key, T& value);

(May need to actually implement all the different variant's differently, so it may not really help much to use a template, but it's much easier for me to write in an answer as a template! ;) )

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top