仿真VC++提供的关键字__uuidof

这个技巧不是针对VC++缺陷的,而是针对VC++扩展语法的。这个技巧的来由,是为了某些希望有一天有可能要脱离Visual C++环境进行开发的人员。为了脱离VC++,你需要谨慎使用它的所有扩展语法。例如本文讨论的__uuidof。我们先来看看一个例子:

  1. class __declspec(uuid("B372C9F6-1959-4650-960D-73F20CD479BA")) Class;
  2. struct __declspec(uuid("B372C9F6-1959-4650-960D-73F20CD479BB")) Interface;
  3.  
  4. void test()
  5. {
  6.    CLSID clsid = __uuidof(Class);
  7.    IID iid = __uuidof(Interface);
  8.    ...
  9. }

这 比起你以前定义uuid的方法简单多了吧?可惜,这样好用的东西,它只在VC++中提供。不过没有关系,我们这里介绍一个技巧,可以让你在几乎所有C++ 编译器中都可以这样方便的使用__uuidof。这里没有说是所有,是因为我们使用了模板特化技术,可能存在一些比较“古老”的C++编译器,不支持该特 性。
 
也许你已经迫不及待了。好,让我们来看看:

  1. #include <string>
  2. #include <cassert>
  3.  
  4. inline
  5. STDMETHODIMP_(GUID) GUIDFromString(LPOLESTR lpsz)
  6. {
  7.     HRESULT hr;
  8.     GUID guid;
  9.     if (lpsz[0] == '{')
  10.     {
  11.         hr = CLSIDFromString(lpsz, &guid);
  12.     }
  13.     else
  14.     {
  15.         std::basic_string<OLECHAR> strGuid;
  16.         strGuid.append(1, '{');
  17.         strGuid.append(lpsz);
  18.         strGuid.append(1, '}');
  19.         hr = CLSIDFromString((LPOLESTR)strGuid.c_str(), &guid);
  20.     }
  21.     assert(hr == S_OK);
  22.     return guid;
  23. }
  24.  
  25. template <class Class>
  26. struct _UuidTraits {
  27. };
  28.  
  29. #define _DEFINE_UUID(Class, uuid)                                        /
  30. template <>                                                                       /
  31. struct _UuidTraits<Class> {                                                    /
  32.     static const GUID& Guid() {                                                /
  33.         static GUID guid = GUIDFromString(L ## uuid);                /
  34.         return guid;                                                                 /
  35.     }                                                                                    /
  36. }
  37.  
  38. #define __uuidof(Class)    _UuidTraits<Class>::Guid()
  39.  
  40. #define DEFINE_CLSID(Class, guid)                                        /
  41.     class Class;                                                                      /
  42.     _DEFINE_UUID(Class, guid)
  43.  
  44. #define DEFINE_IID(Interface, iid)                                         /
  45.     struct Interface;                                                              /
  46.     _DEFINE_UUID(Interface, iid)
  47.  

这样一来,就已经模拟出一个__uuidof关键字。我们可以很方便进行uuid的定义。举例如下:
 
  1. DEFINE_CLSID(Class, "{B372C9F6-1959-4650-960D-73F20CD479BA}");
  2. DEFINE_IID(Interface, "{B372C9F6-1959-4650-960D-73F20CD479BB}");
  3.  
  4. void test()
  5. {
  6.    CLSID clsid = __uuidof(Class);
  7.    IID iid = __uuidof(Interface);
  8.    ...
  9. }

在VC++中,为了与其他编译器以相同的方式来进行uuid的定义,我们不直接使用__declspec(uuid),而是也定义DEFINE_CLSID, DEFINE_IID宏:
 
  1. #define DEFINE_CLSID(Class, clsid)           /
  2.     class __declspec(uuid(clsid)) Class
  3.  
  4. #define DEFINE_IID(Interface, iid)           /
  5.     struct __declspec(uuid(iid)) Interface

这样一来,我们已经在所有包含VC++在内的支持模板特化技术的编译器中,提供了__uuidof关键字。通过它可以进一步简化你在C++语言中实现COM组件的代价。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值