Добавить в цитаты Настройки чтения

Страница 178 из 372

                          free(pszAuthor);

                          free(pszTitle);

                          free(pszText);

                          return S_OK;

          }

В конструкторе CoBook () задается начальное нулевое значение для счетчика числа ссылок на данный объект и увеличивается на 1 глобальный счетчик объектов. Глобальный счетчик объектов используется при принятии решения о возможности удаления из памяти сервера, возможно содержащего не только класс CоBоок, но и какие-то другие классы. Кроме того, члены класса m_bstrTitie и m_bstrAuthor получают в качестве значения пустую строку. Префикс L перед строкой константой говорит о том, что в этой строке на один символ отводится два байта. Для ее преобразования к типу BSTR и размещения в памяти используется функция SysAllocString ().

В деструкторе CоBооk () при уничтожении объекта на 1 уменьшается счетчик объектов и освобождается память, выделенная ранее для заголовка публикации и имени автора. Для освобождения памяти, выделенной под BSTR-строку, используется функция SysFreeString ().

Реализация методов AddRef () и Release () тривиальна и полность соответствует предписанной семантике этих методов.

Метод Query inter face () обеспечивает переход между любыми двумя интерфейсами, реализованными в коклассе совоок. Заметим, что среди этих интерфейсов не только IBook, но и все интерфейсы, от которых прямо или косвенно IBook порожден — IPub и IUnknown. Если запрашиваемый интерфейс не найден, возвращается E_NOINTERFACE. В противном случае вызывается метод AddRef () интерфейса IUnknown, увеличивающий счетчик ссылок на данный объект. Вызвать функцию Release () при освобождении ссылки, полученной в результате вызова QueryInterface () обязан уже клиент.

Методы SetTitle (), SetYear () и SetAuthor () позволяют задать соответственно название, год издания и имя автора книги — нового объекта CоBооk. При передачи в качестве входного аргумента BSTR-строки происходит переразмещение в памяти соответствующей BSTR-строки — члена класса. Для этого используется функция SysReAllocstring ().

Метод GetInfо () возвращает информацию о книге в строке типа BSTR. Вся информация о книге хранится в экземпляре класса CоBооk в виде BSTR-cтрок и целого числа. В процессе формирования результирующей строки все BSTR-строки преобразуются в ANSI-строки. Для выполнения преобразования BSTR-строки в ANSI-строку применяется функция wcstombs (). Первый параметр задает буфер для ANSI-строки, второй — BSTR-строку, третий — размер буфера. Функция SysStringien () позволяет определить длину BSTR-строки в символах. Размер буфера для соответствующей ANSI-строки выбирается в два раза превосходящим длину BSTR-строки, т. к. некоторые Unicode-символы представляются двумя ANSI-символами. Далее в буфер pszText помещается вся выводимая информация, выделяется память под возвращаемую BSTR-строку *pbstrInfо и вызывается функция преобразования ANSI-строки pszText в BSTR-строку *pbstrInfо-mbstowcs().

Для выделения памяти под возвращаемую строку используется функция SysAlloSstringLen (). Первый параметр задает BSTR-строку, первые символы которой, в количестве равном второму параметру, заносятся в новую строку. Задав в качестве первого параметра null мы получаем неинициализированную BSTR-строку длины, заданной вторым параметром.

Последнее действие — освобождение памяти, выделенной под буферы.

Далее определяется и реализуется класс CоJournal, порожденный от интерфейса IJournal. Так как интерфейс IJournal был сам порожден от интерфейса IPub, а последний — от стандартного интерфейса IUnknown, то класс CоJournal должен реализовать чисто виртуальные методы всех этих интерфейсов. Данный класс мало отличается от класса CоBооk, в связи с чем комментарии минимальны.

//////////////////////////////////////////////////

// СоJournal.h: заголовочный файл для класс СоJournal.

//////////////////////////////////////////////////

#ifndef _CoJournal_

#define _CoJournal_

#include "IJournal.h"

#include "iid.h"

class CoJournal:

          public IJournal

{

public:

          CoJournal ();

          virtual ~CoJournal();

          // IUnknown

          STDMETHODIMP Querylnterface(REFIID riid, void** pIFace);

          STDMETHODIMP_(ULONG) AddRef();

          STDMETHODIMP_(ULONG) Release();

          // IPub

           STDMETHOD(SetTitle)(BSTR bstrTitle);

           STDMETHOD(SetYear)(int nYear);

           STDMETHOD(Getlnfo)(BSTR* pbstrlnfo);

           // IJournal

           STDMETHOD(SetNumber)(int nNumber);

private:

           ULONG m_refCount; // Счетчик ссылок

           BSTR m_bstrTitle; // Название публикации

           int m_nYear; // Год публикации

           int m nNumber; // Номер журнала

};

#endif

И теперь реализация класса CоJournal

//////////////////////////////////////////////////

// СоJournal.cpp: реализация класса CoJournal.

//////////////////////////////////////////////////

#include <stdio.h>

#include "CoJournal.h"

#include <stdio.h>

#include "CoJournal.h"

extern ULONG g_objCount; // Счетчик числа объектов





//////////////////////////////////////////////////

// Конструктор и деструктор

//////////////////////////////////////////////////

CoJournal::CoJournal()

{

          m_refCount = 0;

          ++g_obj Count;

          m_bstrTitle = SysAllocString(L"");

}

CoJournal::~CoJournal()

{

          -- g_objCount;

          if(m_b strTitle)

                        SysFreeString(m_bstrTitle);

}

// IUnknown

STDMETHODIMP_(ULONG) CoJournal::AddRef()

{

            return ++m_refCount;

}

STDMETHODIMP_(ULONG) CoJournal::Release()

{

             if (--m_refCount == 0)

             {

                      delete this;

                      return 0;

              }

              else

                      return m_refCount;

}

STDMETHODIMP CoJournal::Querylnterface(REFIID riid, void** pIFace)

{

             if (riid == IID_IUnknown)

             {

                       *pIFace = (IUnknown*)this;

              }

              else if (riid == IID_IJournal)

              {

                        *pIFace = (IJournal*)this;

              }

              else

              {

                        *pIFace = NULL; return E_ NOINTERFACE;

              }

              ((IUnknown*)(*pIFace)) — > AddRef();

               return S_OK;

}

// IPub & IJournal

              STDMETHODIMP CoJournal::SetTitle (BSTR bstrTitle)

              {

                      SysReAllocString(&m_bstrTitle, bstrTitle);