zoukankan      html  css  js  c++  java
  • COM中集合和枚举器笔记(1)概念

    参考:

    http://www.cnblogs.com/clingingboy/archive/2011/06/15/2081786.html

    一.概念

    如同标准库一般,也有容器(即集合类)和迭代器

    void main() {
        // Populate the collection
        vector<long> rgPrimes;
        for (long n = 0; n != 1000; ++n) {
            if (IsPrime(n)) rgPrimes.push_back(n);
        }
    
        // Count the number of items in the collection
        cout << "Primes: " << rgPrimes.size() << endl;
    
        // Iterate over the collection using sequential access
        vector<long>::iterator begin = rgPrimes.begin();
        vector<long>::iterator end = rgPrimes.end();
        for (vector<long>::iterator it = begin; it != end; ++it) {
            cout << *it << " ";
        }
        cout << endl;
    }
    

    二.COM中集合和枚举器的替代品

    ICollection提供基本的2个方法

    Count取得元素数量,Item通过索引获取一个元素.

    除此之外_NewEnum将获取一个与集合相关的枚举器.引用一段话

    通过ICollection操纵数组大体上有两种方法。一种是通过Item属性用数组下标取得元素。这种方式,每次只能取得一个元素,而且要传递下标对象,所以效率比较低下。另一种方法是通过枚举器。数组对象的枚举器通过_NewEnum属性取得。通过枚举器只能按顺序获取元素,但每次可以取得任意多的元素,所以效率较高。ICollection对象可以只实现其中的一种访问方法,也可以两种都实现。ICollection中还有一个重要属性:Count。Count属性返回数组的长度,对于无法确定长度的数组,也可以不实现Count属性。

    [ object, dual ]
    template <typename T>
    interface ICollection : IDispatch {
        [propget]
        HRESULT Count([out, retval] long* pnCount);
    
        [id(DISPID_VALUE), propget]
        HRESULT Item([in] long n, [out, retval] T* pnItem);
    
        [id(DISPID_NEWENUM), propget]
        HRESULT _NewEnum([out, retval] IUnknown** ppEnum);
    };
    
    template <typename T>
    interface IEnum : IUnknown {
        [local]
        HRESULT Next([in] ULONG celt,
            [out] T* rgelt,
            [out] ULONG *pceltFetched);
    
        [call_as(Next)] // Discussed later...
        HRESULT RemoteNext([in] ULONG celt,
            [out, size_is(celt),
            length_is(*pceltFetched)] T* rgelt,
            [out] ULONG *pceltFetched);
    
        HRESULT Skip([in] ULONG celt);
        HRESULT Reset();
        HRESULT Clone([out] IEnum<T> **ppenum);
    }
    

    三.集合和枚举器的使用方法

    通过一个例子来了解集合和枚举器的使用方法

    自定义集合和枚举器接口(暂时不关注实现)

    [dual]
    interface IPrimeNumbers : IDispatch {
        HRESULT CalcPrimes([in] long min, [in] long max);
    
        [propget]
        HRESULT Count([out, retval] long* pnCount);
    
        [propget, id(DISPID_VALUE)]
        HRESULT Item([in] long n, [out, retval] long* pnPrime);
    
        [propget, id(DISPID_NEWENUM)] // Not quite right...
        HRESULT _NewEnum([out, retval] IEnumPrimes** ppEnumPrimes);
    };
    
    interface IEnumPrimes : IUnknown {
        [local]
        HRESULT Next([in] ULONG celt,
            [out] long* rgelt,
            [out] ULONG *pceltFetched);
    
        [call_as(Next)]
        HRESULT RemoteNext([in] ULONG celt,
            [out, size_is(celt),
            length_is(*pceltFetched)] long* rgelt,
            [out] ULONG *pceltFetched);
    
        HRESULT Skip([in] ULONG celt);
        HRESULT Reset();
        HRESULT Clone([out] IEnumPrimes **ppenum);
    };
    

    调用示例

    void main() {
        CoInitialize(0);
    
        CComPtr<IPrimeNumbers> spPrimes;
        if (SUCCEEDED(spPrimes.CoCreateInstance(CLSID_PrimeNumbers))) {
            // Populate the collection
            HRESULT hr = spPrimes->CalcPrimes(0, 1000);
    
            // Count the number of items in the collection
            long nPrimes;
            hr = spPrimes->get_Count(&nPrimes);
            cout << "Primes: " << nPrimes << endl;
    
            // Enumerate over the collection using sequential access
            CComPtr<IEnumPrimes> spEnum;
            hr = spPrimes->get__NewEnum(&spEnum);
    
            const size_t PRIMES_CHUNK = 64;
            long         rgnPrimes[PRIMES_CHUNK];
    
            do {
                ULONG celtFetched;
                hr = spEnum->Next(PRIMES_CHUNK, rgnPrimes, &celtFetched);
                if (SUCCEEDED(hr)) {
                    if (hr == S_OK) celtFetched = PRIMES_CHUNK;
                    for (long* pn = &rgnPrimes[0];
                        pn != &rgnPrimes[celtFetched]; ++pn) {
                            cout << *pn << " ";
                    }
                }
            }
            while (hr == S_OK);
            cout << endl;
    
            spPrimes.Release();
        }
    
        CoUninitialize();
    }
    

    关注Next方法

    HRESULT Next([in] ULONG celt,
        [out] long* rgelt,
        [out] ULONG *pceltFetched);
    

    celt表示要取的元素个数,rgelt用于存储取到的数据指针,pceltFetched表示实际取到的元素个数

    理解这个方式非常关键,由于rgelt存储的指针是外部存储,那么Next方法内部就需要一个的策略来填充这个外部数据的指针,这就从而引出了拷贝策略这个话题,这个到后面实现的时候提到

  • 相关阅读:
    Mybatis传入list的注意点
    synchronized锁
    手撸红黑树
    Vue cdn加速配置
    多线程之BlockingQueue中 take、offer、put、add的一些比较
    线程池
    ThreadLocal
    jdk LocalDateTime mybatis 空指针解决办法
    不同对象中 类型与属性名的属性 进行数据转换
    HashMap 的put方法
  • 原文地址:https://www.cnblogs.com/Clingingboy/p/2760045.html
Copyright © 2011-2022 走看看