Эффективно передавать данные между классами C ++ - PullRequest
4 голосов
/ 03 мая 2010

нужна помощь ...

У меня есть 3 класса, Менеджер , который содержит 2 указателя. Один в класс A другой в класс B . A не знает о B и наоборот.

A выполняет некоторые вычисления и в конце помещает 3 буфера в буфер обмена. Затем B извлекает из буфера обмена 3 поплавка и выполняет свои собственные расчеты. Этот цикл управляется Manager и повторяется много раз (итерация за итерацией).

Моя проблема: Теперь класс A создает вектор чисел с плавающей точкой, в которых нуждается класс B . Этот вектор может иметь более 1000 значений, и я не хочу использовать буфер обмена для его переноса в B , так как он станет временным, даже узким местом, поскольку это поведение повторяется шаг за шагом.

Простое решение состоит в том, что B будет знать A (установите указатель на A ). Другой способ - передать указатель на вектор через Manager . Но я ищу что-то другое, более объектно-ориентированное, которое не нарушит существующее разделение между A и B

Есть идеи?

Большое спасибо

David

Ответы [ 6 ]

9 голосов
/ 03 мая 2010

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

Другими словами: «очередь» похожа на вектор, который вы используете в данный момент. И A, и B будут иметь ссылку на эту очередь. A выполняет вычисления и записывает числа с плавающей точкой в ​​очередь (возможно, по три за раз, если это то, что вам нужно). B проверяет очередь или, возможно, «сигнализирует» A, что очередь готова, и извлекает плавающие числа из очереди для их обработки.

Для получения дополнительной информации, Google (или поиск переполнения стека) для "производитель-потребитель" и / или "очередь" , вы, вероятно, найдете много полезной информации.

(например, Многопоточная рабочая очередь в C ++ )

3 голосов
/ 03 мая 2010

Буфер обмена - это безумный способ для передачи данных между двумя объектами.

Если B реализует универсальный интерфейс, такой как IConsumer, менеджер может передать этот интерфейс A, и A может вызвать метод B напрямую с полезной нагрузкой:

class IConsumer {
public:
   virtual void consume(const vector<float>& data) = 0;
};

class B: public IConsumer {
public:
   virtual void consume(const vector<float>& data) { ... }
   ...
};

class A {
public:
   virtual void produce(IConsumer& consumer) {
      vector<float> data;
      ...
      consumer.consume(data); 
   }
   ...
};

void Manager::tick() {
   a->produce(*b);
}
1 голос
/ 03 мая 2010

B.method (A.method ());

1 голос
/ 03 мая 2010

Создайте вектор и передайте его, используя «передать по ссылке» A и B в ваших итерациях.

0 голосов
/ 03 мая 2010

Как уже отмечалось, вы можете просто использовать std::vector<float> в качестве общего хранилища, если A и B не работают в разных потоках. Manager может управлять этим хранилищем. Когда A начинает свою работу, он может запросить диапазон из этого вектора для сохранения своих результатов. Когда это сделано, Manager вызывает B и передает ему диапазон, который был только что заполнен значениями на A. Это позволяет избежать копирования.

0 голосов
/ 03 мая 2010

Проблема решается, как только вы понимаете, что ни class A, ни class B не должны связываться для управления общим хранилищем данных, так как оно не является эксклюзивным для них. Следовательно, вы правы, предполагая, что Manager должен сделать это.

Для лучшей производительности не передавайте указатель на вектор в A и B. Вместо этого передайте необработанный float*, так как это сохраняет уровень косвенности. Компромиссом было бы передать boost::array &

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...