Доклад: Интерфейсы как решение проблем множественного наследования

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

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

class БытьСтудентом

{

БытьЧеловеком& m_БытьЧеловеком;

public:

БытьСтудентом( БытьЧеловеком& init)

: m_БытьЧеловеком( init)

{ ... };

};

class Студент : public БытьЧеловеком, public БытьСтудентом

{

public:

Студент()

: БытьЧеловеком(), БытьСтудентом( *this)

{ ...};

};

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

Для решения этой задачи есть чрезвычайно красивое, на мой взгляд, решение. Решение заключается в том, чтобы не хранить ссылку на ядро объекта, а получать ее динамически. Для этого применяется оператор приведения типа dynamic_cast, применяемый не к классу, а к объекту в процессе работы программы. Пример:

class БытьСтудентом

{

public:

БытьСтудентом(){};

virtual void Func( void);

// пример функции, обращающейся к ядру объекта

{

БытьЧеловеком* ptr = dynamic_cast< БытьЧеловеком* >( this);

if( ptr)

{

К-во Просмотров: 333
Бесплатно скачать Доклад: Интерфейсы как решение проблем множественного наследования