Гидравлическая система моделирования - PullRequest
0 голосов
/ 18 июня 2019

Мне нужно решить эту проблему: у меня есть гидравлическая система, компоненты которой представляют собой источники, раковины, краны, простые трубки, T-трубки и X-трубки, которые выполняют некоторые действия с потоком воды (источники генерируют поток, T-трубки разделяют егопополам в двух ветвях системы HS трубки X разделяют поток, происходящий из двух ветвей в 1/3 и 2/3, раковина собирает поток и т. д.).Ясно, что я могу иметь более одного источника и более одного приемника.Пользователь устанавливает входной поток для каждого источника (целое число), и я должен предоставить количество воды, собранной в каждом приемнике.

Поэтому я создал базовый класс «Компонент», где я сохранил имя компонентапоток, который он передает следующему компоненту, некоторому геттеру и виртуальному методу для имитации его поведения.Затем я вывел другие классы для других компонентов, реализующих виртуальный метод.В конце концов я создал класс HydraulicSystem, где я сохранил в векторе Component все мои компоненты, но, поскольку «Component» является абстрактным классом, я не могу создавать экземпляры объектов, поэтому я могу хранить только указатели типа Component.В конечном итоге я подумал, что каждый компонент может отследить, что предшествует другому компоненту (2 для труб X, 1 в противном случае), и моделировать HSystem, идущую в обратном направлении от приемников, вот так (я напишу некоторую реализацию рядом с определением, чтобы сделатьлегче читать)

class Component{
public:
//constructor and destructor
//...
//
vector<Component*> getConnected() const;
int simulate() = 0;
private:
string _name;
int flux;
vector<Component*> _connected;

}

class T_Tube : public Component{
public:
//...

 int simulate() { 
for(int i=0;i<_connected.size();i++){
flux = ...
private :
...
}
 return flux;
}

class Sink : public Component{
public :
...
int simulate(){
return getConnected()[0]->simulate();
}
private :
...
}

// other classes
}

затем в классе HSystem, начиная с каждого приемника, я вызываю его метод имитации, который вызывает симуляцию из подключенного к нему компонента и так далее.Этот подход, похоже, работает, но так как мне нужно использовать «новый» для добавления новых компонентов в мою HSystem, где-то мне также нужно освободить эту память, но если я попытаюсь сделать это в деструкторе HSystem, у меня возникнут проблемы, потому что сам компонент имеет вектортипа Компонент.Я также пытался использовать интеллектуальные указатели, но это тоже не сработалоЧего я не могу понять, так это того, что моя программа работает нормально, и у меня нет утечек памяти или ошибок сегментации, если я не забочусь об освобождении памяти?

Как вы думаете, было бы лучше, если бы яОткажитесь от первоначальной идеи поддерживать локально в каждом компоненте информацию о том, кто приходит раньше, и я организую всю HSystem как DAG?В этом случае я хотел бы сделать топологическую сортировку графа, но как я могу его смоделировать?Заранее спасибо

1 Ответ

0 голосов
/ 18 июня 2019

Общий способ - удерживать std::vector<std::unique_ptr<Component>> или std::vector<std::shared_ptr<Component>>.Ссылки на другие Component должны быть либо необработанным указателем (если вы можете быть уверены, что Component все еще существует), либо std::weak_ptr (если нет).

Однако для этого приложения естьнет смысла управлять памятью, как это.Логика такова:

  1. Чтение пользовательского ввода и создание всех компонентов
  2. Моделирование системы
  3. Свободная память?
  4. Выход

Шаг 3 не имеет смысла, потому что шаг 4 все равно сделает это.Так что просто храните необработанные указатели и не беспокойтесь о delete.

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

...