Читаем Сущность технологии СОМ. Библиотека программиста полностью

Отметим, что подсчет элементов больше не является обязательным, так как получатель данных обнаружит конец массива, когда метод IEnumDouble::Next возвратит специальный HRESULT (S_FALSE ).

При наличии приведенного выше определения интерфейса корректной была бы следующая реализация метода:

STDMETHODIMP MyClass::Sum(IEnumDouble *ped, double *psum) {

assert(ped && psum);

*psum = 0; HRESULT hr; do {

// declare a buffer to receive some elements

// объявляем буфер для получения нескольких элементов

enum {

CHUNKSIZE = 2048 };

double rgd[CHUNKSIZE];

// ask data producer to send CHUNKSIZE elements

// просим источник данных послать CHUNKSIZE элементов

ULONG cFetched;

hr = ped->Next(CHUNKSIZE, rgd, &cFetched);

// adjust cFetched to address sloppy objects

// настраиваем cFetched на исправление некорректных объектов

if (hr == S_OK) cFetched = CHUNKSIZE;

if (SUCCEEDED(hr))

// S_OK or S_FALSE

// S_OK или S_FALSE

// consume/use received elements

// потребляем/используем полученные элементы

for (ULONG n = О; п < cFetched; n++) *psum += rgd[n];

}

while (hr == S_OK);

// S_FALSE or error terminates

// завершается по S_FALSE или по ошибке

}

Отметим, что подпрограмма Next возвратит S_OK в случае, если у отправителя имеются дополнительные данные для посылки, и S_FALSE , если пересылка закончена. Также отметим, что в данный код включена защита от некорректных реализации, которые не утруждают себя установкой переменной cFetched при возвращении S_OK (S_OK означает, что все запрошенные элементы были извлечены).

Одно из преимуществ использования идиомы IEnum состоит в том, что она позволяет отправителю откладывать генерирование элементов массива. Рассмотрим следующее определение метода на IDL: HRESULT GetPrimes([in] long nMin, [in] long nMax, [out] IEnumLong **ppe);

Разработчик объекта может создать специальный класс, который генерирует по требованию простые числа и реализует интерфейс IEnumLong:

class PrimeGenerator : public IEnumLong {

LONG m_cRef;

// СОМ reference count

// счетчик ссылок СОМ

long m_nCurrentPrime;

// the cursor

// курсор long m_nMin;

// minimum prime value

// минимальное значение простого числа

long m_nMax;

// maximum prime value

// максимальное значение простого числа

public:

PrimeGenerator(long nMin, long nMax, long nCurrentPrime) : m_cRef(0), m_nMin(nMin), m_nMax(nMax),

m_nCurrentPrime(nCurrentPrime) { }

// IUnknown methods

// методы IUnknown

STDMETHODIMP QueryInterface(REFIID riid, void **ppv);

STDHETHODIMP_(ULONG) AddRef(void);

STDMETHODIMP_(ULONG) Release(void);

// IEnumLong methods

// методы IEnumLong

STDMETHODIMP Next(ULONG, long *, ULONG *);

STDMETHODIMP Skip(ULONG);

STDMETHODIMP Reset(void);

STDMETHODIMP Clone(IEnumLong **ppe);

};

Реализация генератора Next будет просто порождать запрошенное количество простых чисел:

STDMETHODIMP PrimeGenerator::Next(ULONG cElems, long *prgElems, ULONG *pcFetched) {

// ensure that pcFetched is valid if cElems > 1

// удостоверяемся, что pcFetched легален, если cElems больше единицы

if (cElems > 1 && pcFetched == 0) return E_INVALIDARG;

// fill the buffer

// заполняем буфер

ULONG cFetched = 0;

while (cFetched < cElems && m_nCurrentPrime <= m_nMax) {

prgElems[cFetched] = GetNextPrime(m_nCurrentPrime);

m_nCurrentPrime = prgElems[cFetchcd++];

} if (pcFetched)

// some callers may pass NULL

// некоторые вызывающие программы могут передавать NULL

*pcFetched = cFetched;

return cFetched == cElems ? S_OK : S_FALSE;

}

Отметим, что даже если имеются миллионы допустимых значений, одновременно в памяти будет находиться лишь малое их число.

Методу генератора Skip нужно просто генерировать и отбрасывать запрошенное количество элементов:

STDMETHODIMP PrimeGenerator::Skip(ULONG cElems) {

ULONG cEaten = 0; while (cEaten < cElems && m_nCurrentPrime <= m_nMax) {

m_nCurrentPrime = GetNextPrime(m_nCurrentPrime);

cEaten++; }

return cEaten == cElems ? S_OK : S_FALSE;

}

Метод Reset устанавливает курсор на начальное значение:

STDMETHODIMP PrimeGenerator::Reset(void) {

m_nCurrentPrime = m_nMin;

return S_OK;

}

а метод Clone создает новый генератор простых чисел на основе минимума, максимума и текущих значений, выданных существующим генератором:

STDMETHODIMP PrimeGenerator::Clone(IEnumLong **ppe) {

assert(ppe);

*рре = new PrimeGenerator(m_nMin, m_nMax, m_nCurrent);

if (*ppe) (*ppe)->AddRef();

return S_OK;

}

При наличии реализации PrimeGenerator реализация метода GetPrimes текущим объектом становится тривиальной:

STDMETHODIMP MyClass::GetPrimes(long nМin, long nMax, IEnumLong **ppe) {

assert(ppe);

*ppe = new PrimeGenerator (nMin, nMax, nMin);

if (*ppe) (*ppe)->AddRef();

return S_OK;

}

Большая часть этой реализации находится теперь в классе PrimeGenerator, а не в классе объекта.

<p>Динамический вызов в сравнении со статическим</p>
Перейти на страницу:

Похожие книги

1С: Бухгалтерия 8 с нуля
1С: Бухгалтерия 8 с нуля

Книга содержит полное описание приемов и методов работы с программой 1С:Бухгалтерия 8. Рассматривается автоматизация всех основных участков бухгалтерии: учет наличных и безналичных денежных средств, основных средств и НМА, прихода и расхода товарно-материальных ценностей, зарплаты, производства. Описано, как вводить исходные данные, заполнять справочники и каталоги, работать с первичными документами, проводить их по учету, формировать разнообразные отчеты, выводить данные на печать, настраивать программу и использовать ее сервисные функции. Каждый урок содержит подробное описание рассматриваемой темы с детальным разбором и иллюстрированием всех этапов.Для широкого круга пользователей.

Алексей Анатольевич Гладкий

Программирование, программы, базы данных / Программное обеспечение / Бухучет и аудит / Финансы и бизнес / Книги по IT / Словари и Энциклопедии
1С: Управление торговлей 8.2
1С: Управление торговлей 8.2

Современные торговые предприятия предлагают своим клиентам широчайший ассортимент товаров, который исчисляется тысячами и десятками тысяч наименований. Причем многие позиции могут реализовываться на разных условиях: предоплата, отсрочка платежи, скидка, наценка, объем партии, и т.д. Клиенты зачастую делятся на категории – VIP-клиент, обычный клиент, постоянный клиент, мелкооптовый клиент, и т.д. Товарные позиции могут комплектоваться и разукомплектовываться, многие товары подлежат обязательной сертификации и гигиеническим исследованиям, некондиционные позиции необходимо списывать, на складах периодически должна проводиться инвентаризация, каждая компания должна иметь свою маркетинговую политику и т.д., вообщем – современное торговое предприятие представляет живой организм, находящийся в постоянном движении.Очевидно, что вся эта кипучая деятельность требует автоматизации. Для решения этой задачи существуют специальные программные средства, и в этой книге мы познакомим вам с самым популярным продуктом, предназначенным для автоматизации деятельности торгового предприятия – «1С Управление торговлей», которое реализовано на новейшей технологической платформе версии 1С 8.2.

Алексей Анатольевич Гладкий

Финансы / Программирование, программы, базы данных