在COM中奇怪地使用null智能指针

时间:2017-07-06 05:42:06

标签: com

如图所示,我不知道为什么m_spServer,一个接口指针,当测试为null时,可以用来调用成员函数CreateInstance()。谁能告诉我为什么?

https://domainname.com/index.php?route=fashion

这是接口定义,我在接口中找不到CreateInstance(),也没有接口指针定义。 enter image description here

1 个答案:

答案 0 :(得分:1)

仔细查看代码:

m_spServer.CoCreateInstance(...);

有两点需要注意:

  1. m_spSever 不是实际指针。相反,它是类型为CComPtr智能指针模板类的实例。也就是说,它已经重载->运算符以取消引用底层原始指针(IAtlasServer*)。同样,==运算符被重载以测试nullness。

  2. 该方法被调用为.CoCreateInstance,带有“点”。不是->CoCreateInstance带有“箭头”。智能指针永远不会为“null”。它包含的指针非常好。这意味着该方法将在CComPtr实例本身上调用,而不是在底层原始指针上调用。

  3. 让我们看一下CComPtr :: CoCreateInstance的实现。

    template <class T>
    class CComPtrBase
    {
        ...
    
        bool operator==(_In_opt_ T* pT) const throw()
        {
            return p == pT;
        }
    
        ...
    
        _Check_return_ HRESULT CoCreateInstance(
            _In_ REFCLSID rclsid,
            _Inout_opt_ LPUNKNOWN pUnkOuter = NULL,
            _In_ DWORD dwClsContext = CLSCTX_ALL) throw()
        {
            ATLASSERT(p == NULL);
            return ::CoCreateInstance(rclsid, pUnkOuter, dwClsContext, __uuidof(T), (void**)&p);
        }
    
        ...
    
        T* p;
    
        ...
    };
    

    您将看到CComPtr包装名为“p”的本机(“原始”)指针成员变量。重载的== operator测试针对与之比较的本机指针类型。名为CoCreateInstance的CComPtr上的方法只是声明它包含的原始指针已经为空,然后尝试使用原始指针作为“out”参数进行本机CoCreateInstance调用。

    智能指针非常棒,非常适合COM编程。 CComPtr的析构函数会自动地在底层原始指针上调用“Release”。如果使用正确,您将避免常见的引用计数问题,而无需考虑“AddRef”和“Release”。