Могут ли некоторые члены класса быть доступны только базовым классам?

у меня есть Widget класс и CompositeWidget это вытекает из этого. CompositeWidget добавляет поведение управления детьми. Widget Конструктор занимает CompositeWidget* Параметр в качестве родителя виджета. Мне нужно использовать этот родительский указатель для доступа к некоторым функциям в CompositeWidget, Например:

Widget::Widget(CompositeWidget* parent)
{
parent_->AddChild(*this);
}

Это заставляет меня создавать публичный метод CompositeWidget::AddChild, Возможно ли сохранить этот интерфейс закрытым для иерархии классов (немного похоже наprotected доступ — ограничен базовыми классами)? Думал ли я о такой проблеме как дизайнер?

Редактировать: Я стараюсь избегать дружбы (если это возможно в этом случае).

1

Решение

Использовать friend ключевое слово.

class Widget { ... };

class CompositeWidget {
friend class Widget;
};

Тем не менее, вы можете в качестве альтернативы вставить virtual метод AddChild на Widget учебный класс.

1

Другие решения

Это заставляет меня создавать публичный метод

Нет, вы можете заявить:

friend class Widget;

В объявлении CompositeWidget. Тем не мение…

Я делаю дизайн ложного па

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

3

Ответьте на свой конкретный вопрос: объявите Widget быть friend вашей CompositeWidget и сделать AddChild private член.

В качестве альтернативы, переместите управление детьми в CompositeWidget, Шаблоны проектирования Книга имеет расширенное обсуждение этого вопроса в их разделе о Композитный Узор:

Решение включает компромисс между безопасностью и прозрачностью:

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

Мы подчеркнули прозрачность над безопасностью в этом паттерне. если ты
выбрать безопасность, то иногда вы можете потерять информацию о типе и иметь
преобразовать компонент в композит. Как вы можете сделать это без
прибегая к небезопасному броску?

Далее они приводят длинный пример кода, который по сути сводится к этой схеме, где CompositeWidget содержит дочернее управление:

class Widget
{
public:
//
virtual Composite* GetComposite() { return 0; }
}

class CompositeWidget: public Widget
{
public:
void AddChild(Component*);
// ...
virtual Composite* GetComposite() { return this; }
};

class LeafWidget: public Widget
{
// no child management here
};

GetComposite позволяет запросить виджет, чтобы увидеть, является ли он составным. Вы
может выполнять AddChild безопасно на композит он возвращается.

0
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector