2015-07-14 3 views
1

У меня есть система инвентаризации, в которой хранятся типы «Item», которые являются абстрактным классом. У меня есть производный класс под названием «Skates». Программа позволяет пользователю добавлять «Skates» в вектор указателей «Item». Пользователь вводит модель и идентификатор коньков, и я создаю объект «Skates» с этими параметрами. Затем я использую указатель «Item», чтобы указать на объект «Skates» и добавить его в вектор. Когда пользователь хочет отредактировать объект «Коньки», мне нужно выполнить динамическое преобразование его обратно в объект «Коньки», а затем отредактировать его.Как сделать систему инвентаризации консоли динамической

std::vector<Item*> ItemCollection; 
Item * item = new Skates("model1", 1); 
ItemCollection.push_back(item); 
//To retrieve it 
Skates * skatesToEdit = dynamic_cast<Skates*>(ItemCollection[0]); 

Проблема я столкнулся сейчас на счет нового производного класса, класса «скейтборд», например. Я не хочу, чтобы создать новый метод для обработки редактирования класса «скейтборд», как:

Skateboard * skateboardToEdit = dynamic_cast<Skateboard*>(ItemCollection[0]); 

Так как это будет означать, что каждый раз, когда я делаю новый производный класс, мне нужно, чтобы написать этот же стиль коды каждый раз. Поэтому я хотел бы знать, есть ли способ заставить приложение динамически знать, что такое производный класс, без необходимости его указывать. Таким образом, он должен иметь возможность определять тип данных, а затем предлагать пользователю редактировать любое свойство, которое у него есть (поскольку цель состоит в том, чтобы пользователи могли сначала редактировать объект) одним динамическим методом, который, я думаю, должен быть невозможным.

+0

Вам нужно знать, что предмет? Не могли бы вы создать чистую виртуальную функцию для элемента, переопределить ее в Skates и Skateboard и просто вызвать виртуальную функцию как функцию-член ItemCollection [x]? Таким образом, вам не нужно знать, что такое элемент: система будет сортировать его для вас. – cup

+0

Извините, я не вижу, как это позволит мне вернуть Item как производный класс для редактирования свойств, специфичных для этого производного класса. Возможно, я недопонимаю. – Stein121

ответ

1

Я бы предположил, что, возможно, наследование не то, что вам нужно здесь. Вместо того, чтобы иметь такие классы, как Skates, Skateboard, рассмотрим наличие только класса Item, который представляет собой набор ключевых значений, представляющих свойства. Таким образом, вы действительно не заботитесь о классе элемента, и вы можете динамически переименовывать и редактировать свойства.

+0

Я знаю, что у вас означает просто класс «Item», но есть две причины, по которым мне нужно наследование: для учета разных видов элементов и потому, что это назначение, которое отмечает для наследования – Stein121

+0

@ Stein121 вам не нужно наследование для этого действительно. Вы можете просто иметь тип поля и хранить его там. Наследование используется для моделирования сложных отношений между классами. Это не подходит для обозначения разных вещей. – Andrey

+0

Я понимаю, что вы хотите просто добавить новые свойства, если есть новый тип объекта для хранения. Наверное, у меня на самом деле нет выбора. – Stein121

0

Как я понимаю, у вас есть методы для редактирования полученных элементов, как void editSkates(Skates*), void editSkateboard(Skateboard*) и т.д.

Затем вы можете применить Visitor pattern. Создать абстрактный класс Visitor с visit методом, перегруженной для каждого отдельного Item подкласса:

class ItemVisitor{ 
public: 
    virtual void visit(Skates*) = 0; 
    virtual void visit(Skateboard*) = 0; 
    //... one function for every subclass 
}; 

Создать virtual void accept(ItemVisitor&) = 0; метод в вашем Item классе. В каждом подклассе, скажем, Skates, переопределить этот метод для вызова правильный visit:

void Skates::accept(ItemVisitor& visitor){ 
    visitor.visit(this); 
} 

Теперь вы можете наследовать ItemVisitor делать определенные вещи с конкретными подклассов, например, так:

class EditVisitor: public ItemVisitor{ 
public: 
    virtual void visit(Skates* skates){ 
     skates->editSpecialSkatesProperty(); 
    } 

    virtual void visit(Skateboard* skateboard){ 
     skateboard->editSpecialSkateboardProperty(); 
    } 
}; 

И, наконец, сделать эта конкретная вещь с вашим общим Item * item пример:

EditVisitor edit; 
item->accept(edit); 
+0

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

Смежные вопросы