Шрифт:
SysFreeString(m_bstrTitle);
if(m_bstrAuthor)
SysFreeString(m_bstrAuthor);
}
// IUnknown
STDMETHODIMP_(ULONG) CoBook::AddRef
{
return ++m_refCount;
}
STDMETHODIMP_(ULONG) CoBook::Release
{
if (--m_refCount == 0)
{
delete this;
return 0;
}
else
return m_refCount;
}
STDMETHODIMP CoBook::Querylnterface(REFIID riid, void** pIFace)
{
if (riid == IID_IUnknown)
{
*pIFace = (IUnknown*)this;
}
else if (riid == IID_IPub)
}
*pIFace = (IPub*)this;
}
else if (riid == IID_IBook)
{
*pIFace = (IBook*)this;
}
else
{
*pIFace = NULL; return E_NOINTERFACE;
}
((IUnknown*)(*pIFace))->AddRef;
return S OK;
}
//IPub&IBook
STDMETHODIMP CoBook::SetTitle (BSTR bstrTitle)
{
SysReAllocString(&m_bstrTitle, bstrTitle);
return S_OK;
}
STDMETHODIMP CoBook::SetYear(int nYear)
{
m_nYear = nYear;
return S_OK;
}
STDMETHODIMP CoBook::SetAuthor(BSTR bstrAuthor)
{
SysReAllocString(&m_bstrAuthor, bstrAuthor);
return S_OK;
}
STDMETHODIMP CoBook::Getlnfo(BSTR *pbstrInfo)
{
char* pszTitle = NULL;
char* pszAuthor = NULL;
char* pszText = NULL;
int nAuthorLength, nTitleLength;
nAuthorLength = SysStringLen(m_bstrAuthor);
nTitleLength = SysStringLen(m_bstrTitle);
pszAuthor = (char*)malloc(2*nAuthorLength);
pszTitle = (char*)malloc(2*nTitleLength);
pszText = (char*)malloc(2*nAuthorLength + 2*nTitleLength + 50);
wcstombs(pszTitle, m_bstrTitle, 2*nTitleLength);
wcstombs(pszAuthor, m_bstrAuthor, 2*nAuthorLength);
sprintf(pszText,
"Book\n\nAuthor: %s\nTitle: %s\nYear: %d", pszAuthor, pszTitle, m_nYear);
*pbstrInfo = SysAllocStringLen(NULL, 2*strlen(pszText));
mbstowcs (*pbstrInfo, pszText, 2*strlen (pszText));
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, в связи с чем комментарии минимальны.