Шаг 193.
Среда программирования Visual C++.
Повторное использование объектов в C++ и СОМ

    На этом шаге мы рассмотрим особенности повторого использования объектов в C++ и COM.

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

#include "Acme.h"        // Содержит определение класса AcmeViewer.
                         // Определяет функции-члены SetFile() и Display().
class MyViewer
{
  protected:
    AcmeViewer m_obj;
  public:
    MyViewer() {m_obj.SetFile("C:\images\scully.gif", AV_TYPE_GIF);}
    void DisplayGif() {m_obj.Display(); } 
};

    Здесь определяется простой класс MyViewer, содержащий экземпляр определенного ранее класса AcmeViewer. MyViewer повторно использует код, содержащийся в AcmeViewer. Конструктор MyViewer инициализирует вложенный объект AcmeViewer, и функция MyViewer::DisplayGif() пользуется услугами последнего. Класс MyViewer способен управлять доступом к объекту AcmeViewer и его функциям.

    Наследование - мощная методика повторного использования кода, представляющего собой краеугольный камень C++. С учетом сказанного ранее о классе AcmeViewer становится очевидным, что следующее объявление:

#include "Acme.h"

class MyViewer : public AcmeViewer
{
  public:
    MyViewer() {SetFile("C:\images\scully.gif", AV_TYPE_GIF);}
}

позволит Вам вызывать открытые или защищенные функции-члены AcmeViewer как функции-члены, принадлежащие объекту MyViewer:

MyViewer aViewer; 
aViewer.Display();

    COM поддерживает вложение, но реализация наследования в этой технологии отличается от принятой в C++. В данном примере класс MyViewer наследует функциональность класса AcmeViewer. MyViewer доступны как открытые, так и защищенные функции-члены AcmeViewer. Этот тип наследования известен под названием наследования реализации (implementation inheritance).

    СОМ наследование реализации не поддерживает. В этой технологии существует строгое логическое разделение между интерфейсом предоставляемым СОМ-объектом, и реализацией этого интерфейса. Опубликованный СОМ-интерфейс, идентифицируемый в глобальном масштабе по его GUID, является неизменным (immutable) - он никогда не будет модифицирован. Хотя число СОМ-объектов, реализующих тем или иным способом его функциональность, не ограничено, клиенты всегда будут знать, как обращаться к любому из этих объектов. Интерфейс является соглашением между СОМ-сервером и клиентом, в котором четко определено, какие данные объект получает а какие - возвращает.

    Наследование реализации приводит к зависимости производного класса от базового. При изменении реализации базового класса производные в некоторых случаях перестают работать корректно, и поэтому иногда приходится переписывать их заново. Это весьма сложно в крупномасштабных разработках, особенно если у Вас нет доступа к исходному тексту базовых классов. Решение таких проблем несколько упрощается при отделении интерфейса от его реализации в СОМ; но это также означает, что Вы не можете повторно использовать СОМ-компоненты, создавая их производные, как в случае с классами C++.

    В СОМ поддерживается форма наследования, известная как наследование интерфейса (interface inheritance). В C++ интерфейсы реализованы в виде абстрактных классов, содержащих только виртуальные функции, определяющие, но не реализующие методы интерфейса. Наследуя интерфейс, Вы определяете структуру таблицы vtable, в которой будут находиться указатели на экземпляры методов. Например, следующее определение создаст должным образом структурированную vtable с указателями на три метода IUnknown и на методы, определенные в IEncoder:

IEncoder : public IUnknown 
{
  // Здесь объявляются методы IEncoder. 
}

    Именно благодаря неизменности СОМ-интерфейсов становится возможным их наследование. Вы, создавая производные СОМ-интерфейсы из любого другого СОМ-интерфейса, полностью уверены, что никто не изменит определение интерфейса родителя и не нарушит структуру Вашей vtable.

    На следующем шаге мы рассмотрим один из способов повторного использования COM-объектов - вложение.




Предыдущий шаг Содержание Следующий шаг