Страница 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);