Подтвердить что ты не робот

Неправильная ли практика для дочернего объекта иметь указатель на родителя?

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

control[n]->onClick();

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

Size windowsize = parent->getSize();

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

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

4b9b3361

Ответ 1

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

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

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

Ответ 2

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

Ответ 3

Фактически GOF Составной шаблон проектирования основан на Явных родительских ссылках.

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

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

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

Ответ 4

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

Ответ 5

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

Ответ 6

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

Ответ 7

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

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