Это плохая практика для дочернего объекта иметь указатель на своего родителя? - PullRequest
13 голосов
/ 16 сентября 2010

В приложении C ++, скажем, у меня есть класс окна, в котором есть несколько экземпляров класса управления.Если бы мое окно хотело уведомить элемент управления о том, что оно было щелкнуто, я мог бы использовать:

control[n]->onClick();

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

Size windowsize = parent->getSize();

Будет ли это считаться плохой практикой или каким-либо другим образом противоречить значениям объектно-ориентированного программирования?Если да, то какой он «правильный» способ сделать это?

Как побочный вопрос, лучше ли было бы иметь вектор класса или класса *?Стоит ли дополнительной сложности для увеличения скорости?(Изменения в векторе будут редкими). ​​

Ответы [ 7 ]

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

Вы можете рассматривать иерархию элементов управления как структуру данных в виде древовидного графа;когда вы визуализируете это таким образом, для элемента управления вполне разумно иметь указатель на его родителя.

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

Если вы храните указатели, обязательно используйте любой из нихумный указатель некоторого вида или контейнер указателя;в противном случае исключение безопасности - это избиение.

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

Отлично.Это общий шаблон в UI-фреймворках.Например, класс .NET Windows Forms Control имеет конструктор для указания родителя (http://msdn.microsoft.com/en-us/library/wawy06xc.aspx).

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

Фактически, шаблон GOF Composite основан на явных родительских ссылках.

Явные родительские ссылки. Ведение ссылок от ребенка компоненты к их родителю могут упростить обход и управление композитной структуры. Родитель ссылка упрощает движение вверх структурирование и удаление компонента. Родительские ссылки также помогают в поддержке Цепочка ответственности (223) шаблон. Обычное место для определения родительская ссылка находится в компоненте учебный класс. Листовые и составные классы могут наследовать ссылку и операции, которые управляют этим.

При наличии родительских ссылок важно поддерживать инвариант, что все дети композитного имеют как их родительский композит, который в свою очередь имеет их как дети. Самый простой способ убедитесь, что это изменить компонент родитель, только когда он добавляется или снято с композита. Если это может быть реализован один раз в Add и Удалить операции из Composite класс, то он может быть унаследован всеми подклассы, и инвариант будет поддерживаться автоматически.

Поэтому, я полагаю, есть место для такого дизайна, в зависимости от фактических требований и контекста.

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

Нет, все в порядке.Единственная проблема заключается в том, что это увеличивает уровень связи между экземплярами.Кроме того, если вы рассматриваете использование интеллектуальных указателей, как указано выше, убедитесь, что вы делаете ссылку на родительский элемент «слабым».Предполагая, что деревья вашего окна не слишком глубокие, вы можете определить родительский dyuamica1ly, начиная с известного верхнего окна.

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

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

1 голос
/ 02 июля 2013

Если вам нужно это сделать, рассмотрите возможность передачи родителя как const*.

0 голосов
/ 03 июля 2013

Это не плохо. Например, в виджетах Qt каждый виджет будет иметь указатель на родителя, даже без использования const*.

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

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