Стек полиморфизованных классов

#c #arrays #polymorphism #derived

#c #массивы #полиморфизм #производный

Вопрос:

уважаемые профессионалы в области C . У меня проблема. У меня есть программа, в которой есть 1 абстрактный класс base_class и 2 производных класса: sippeers и dbget. Он также имеет 2 потока. Первый поток получает команды от пользователя, второй поток выполняет эти команды. Оба производных класса представляют разные команды. Итак, я должен создать какой-то стек, куда я должен помещать пользовательские команды из первого потока и передавать их для обработки во втором потоке. Чтобы создать один стек для всех команд, мне пришлось использовать полиморфизм. Сначала я попытался использовать std::list. Но возникла первая проблема: я не могу составить список абстрактных классов. Затем я попытался использовать boost::ptr_list, но возникла вторая проблема: классы, созданные в первом потоке, исчезают с завершением процедуры, которая их создала. Таким образом, указатели становятся незаконными. Вопрос: какую реализацию я должен использовать? Похоже, я должен хранить каждую копию производного класса. Но где?

Ответ №1:

std::queue of shared_ptr<base_class> является наиболее простым решением для передачи классов из одного потока в другой, не беспокоясь об управлении памятью. В сочетании с условной переменной для обозначения того, что очередь не пуста, поэтому поток-потребитель может ждать.

Что касается части полиморфизма, имейте дополнительную виртуальную функцию (execute()?), Поэтому поток-потребитель не должен знать, какой класс он на самом деле получает.

Комментарии:

1. Будет ли это решением? Я мог бы использовать команды std::list<boost::shared_ptr<base_class>> Первый поток мог бы поместить указатели в этот список, второй поток мог бы сделать что-то вроде: while (!commands.empty()) { base_command c = команды. front(); команды.pop_front(); }

2. За исключением shared_ptrs (о котором мы не знали в то время), это (упрощенное) решение, которое мы используем. Мы используем std::queue, потому что это все, что нужно. Вы могли бы использовать std::list, если хотите удалить / заменить некоторые экземпляры команд. Не забудьте ‘переменную условия’ / монитор / семафор, если вы хотите заблокировать пустую / полную очередь.

Ответ №2:

Сначала я попытался использовать std::list. Но возникла первая проблема: я не могу составить список абстрактных классов.

Однако вы можете создать, std::list содержащий указатели на абстрактный базовый класс, например

 std::list<base_class *> commands;
  

Затем я попытался использовать boost::ptr_list, но возникла вторая проблема: классы, созданные в первом потоке, исчезают с завершением процедуры, которая их создала. Таким образом, указатели становятся незаконными.

Вы имеете в виду, что новые команды создаются в стеке первого потока? Не делайте этого — первый поток не знает, когда второй поток закончил обработку команд, поэтому первый поток не должен определять, когда они заканчиваются. Просто позвольте первому потоку распределять объекты с помощью new .

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