Как будет содержаться функция вызова класса-члена, содержащая класс - Композиция в C ++ - PullRequest
0 голосов
/ 14 сентября 2010

Это общий вопрос проектирования с точки зрения C ++.У меня есть контейнерный класс, который содержит объекты 2 других классов.

Из контейнерного класса мы можем вызывать методы содержащегося объекта класса «как мы имеем дескриптор к содержащемуся объекту класса», например objContainedClass1-> SomeMthod ();

Но я хочу знать, как содержащийся в объекте класса (objContainedClass1) доступ к методам класса контейнера.

Я могу придумать следующие способы:

  1. Объект класса контейнера передает указатель на себя (этот указатель) на содержащийся конструктор класса.Используя этот указатель, содержащийся класс может обращаться к методам класса контейнера.

  2. Сделать некоторые функции в классе контейнера статическими.

Любойбольше идей для достижения этого?

Спасибо

Ответы [ 5 ]

6 голосов
/ 14 сентября 2010

Не, как правило, это плохой дизайн для класса, чтобы знать о своем контейнере.Обычно это означает, что вы нарушили принцип единственной ответственности.

2 голосов
/ 14 сентября 2010

Оба способа подходят для разных целей. Если все, что вам нужно, это вызвать статические методы, # 2 в порядке. Но если вам нужен доступ к методам экземпляра класса контейнера, вам нужно иметь указатель класса контейнера, поэтому путь # 1 - это путь.

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

1 голос
/ 14 сентября 2010

Существует несколько вариантов с плохим ухудшением.

Вы можете сделать содержащиеся классы частью класса контейнера, если они не используются за его пределами.

Вы можете сделать контейнер другом из классов (yuck).

Вы можете передать ссылку или boost :: shared_ptr в контейнер вместо необработанного указателя. Лучший метод зависит от продолжительности жизни каждого. Избегайте необработанных указателей, если можете.

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

0 голосов
/ 16 сентября 2010

Не. Ответственность контейнерного класса состоит в том, чтобы содержать вещи, ничего больше. Если вам нужен ваш контейнерный класс для выполнения действий, основанных на том, что содержится внутри, попросите третий объект выполнить эти действия. Например, я предполагаю, что вы реорганизуете или иным образом модифицируете коллекцию классов на основе содержимого классов. Вместо того, чтобы пытаться сделать это внутри содержащихся классов, выполните это действие в классе, который использует контейнер в качестве зависимости.

0 голосов
/ 14 сентября 2010
  • Сделать некоторые функции в классе контейнера статическими.

Это то, что можно назвать "прощай, ООП!"и я воздерживаюсь от его максимально возможного использования.

  • Объект класса контейнера передает указатель на себя (этот указатель) на содержащийся конструктор класса.Используя этот указатель, содержащийся класс может обращаться к методам класса контейнера.

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

Для дальнейшего отделениясодержащиеся из содержащих классы, события или сообщения также могут быть использованы.Содержащиеся объекты не знают, где они содержатся, но вместо этого отправляют сообщения.Содержащий объект при создании содержащихся объектов регистрируется как получатель сообщений от них.Этот метод позволяет сделать объекты буквально независимыми, но требует (1) некоторой структуры обмена сообщениями, (2) из-за статической природы C ++, довольно сложной для реализации, и (3) также необходим дополнительный уровень документации, поскольку интерфейс классов теперь включает в себя обмен сообщениями.

В противном случае, дважды подумайте, почему содержащиеся объекты должны вызывать методы контейнера.Может быть, вам нужно разделить контейнер с некоторыми общими функциями на 3-й класс?Если содержащиеся объекты действительно являются активными объектами и являются логическим источником событий в системе, то вам может действительно потребоваться некоторая базовая система обработки событий / сообщений, чтобы контейнер мог эффективно запрашивать / отслеживать изменения состояния в содержащихся объектах.

...