Я строю иерархию объектов, которые обертывают примитивные типы, например целые числа, булевы, поплавки и т. Д., А также типы контейнеров, такие как векторы, карты и наборы. Я пытаюсь (иметь возможность) создавать произвольную иерархию объектов и иметь возможность легко устанавливать/получать свои значения. Эта иерархия будет передана другому классу (не упомянутому здесь), и из этого представления будет создан интерфейс. Это цель этой иерархии, чтобы иметь возможность создать представление GUI из этих objects.To быть более точным, у меня есть что-то вроде этого:Как создать правильную иерархию объектов в C++
class ValObject
{
public:
virtual ~ValObject() {}
};
class Int : public ValObject
{
public:
Int(int v) : val(v) {}
void set_int(int v) { val = v);
int get_int() const { return val; }
private:
int val;
};
// other classes for floats, booleans, strings, etc
// ...
class Map : public ValObject {}
{
public:
void set_val_for_key(const string& key, ValObject* val);
ValObject* val_for_key(const string& key);
private:
map<string, ValObject*> keyvals;
};
// classes for other containers (vector and set) ...
Клиент должен иметь возможность создавать и произвольной иерархии объекты, установить и получить их значения с легкостью, и я, как младший программист, должен научиться правильно создавать классы для чего-то вроде этого.
Основная проблема, с которой я столкнулся, заключается в том, как установить/получить значения через указатель на базовый класс ValObject
. Сначала я подумал, что могу просто создать множество функций в базовом классе, например set_int
, get_int
, set_string
, get_string
, set_value_for_key
, get_value_for_key
и т. Д. И заставить их работать только для правильных типов. Но тогда у меня было бы много случаев, когда функции ничего не делали и просто загрязняли мой интерфейс. Моя вторая мысль была создавать различные прокси-объекты для установки и получения различных значений, например,
class ValObject
{
public:
virtual ~ValObject() {}
virtual IntProxy* create_int_proxy(); // <-- my proxy
};
class Int : public ValObject
{
public:
Int (int v) : val(v) {}
IntProxy* create_int_proxy() { return new IntProxy(&val); }
private:
int val;
};
class String : public ValObject
{
public:
String(const string& s) : val(s) {}
IntProxy* create_int_proxy() { return 0; }
private:
string val;
};
Клиент может затем использовать этот прокси-сервер для установки и получения значений в Int через ValObject:
ValObject *val = ... // some object
IntProxy *ipr = val->create_int_proxy();
assert(ipr); // we know that val is an Int (somehow)
ipr->set_val(17);
Но с этим дизайном у меня все еще слишком много классов для объявления и реализации в различных подклассах. Правильно ли это? Есть ли альтернативы?
спасибо.
Я думаю, что это определенно неправильный дизайн и слишком сложный. Чего вы пытаетесь достичь? – Philipp
Я пытаюсь (иметь возможность) создавать произвольную иерархию объектов и иметь возможность легко устанавливать/получать их значения. Эта иерархия будет передана другому классу (не упомянутому здесь), и из этого представления будет создан интерфейс. Это цель этой иерархии, чтобы иметь возможность создавать представление GUI из этих объектов. – GavinTael
Предлагаю вам скопировать свой комментарий и добавить его в начале вашего вопроса. Это будет намного легче ответить на ваш вопрос, если мы знаем цель не только детали реализации. –