posts - 1, comments - 0, trackbacks - 0, articles - 0
   ::  ::  :: 联系 ::  :: 管理

2008年7月2日

转自CSDN 许式伟的专栏

  这个技巧不是针对VC++ 6.0缺陷的,而是针对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     }


  这比起你以前定义uuid的方法简单多了吧?可惜,这样好用的东西,它只在VC++中提供。不过没有关系,我们这里介绍一个技巧,可以让你在几乎所有C++ 编译器中都可以这样方便的使用__uuidof。这里没有说是所有,是因为我们使用了模板特化技术,可能存在一些比较“古老”的C++编译器,不支持该特性。
 
  也许你已经迫不及待了。好,让我们来看看:
 
 1     #include <string>
 2     #include <cassert>
 3      
 4     inline STDMETHODIMP_(GUID) GUIDFromString(LPOLESTR lpsz)
 5     {
 6         HRESULT hr=S_FAIL;
 7         GUID guid;
 8         if(lpsz[0]=='{')
 9         {
10             hr=CLSIDFromString(lpsz,&guid);
11         }
12         else
13         {
14             std::basic_string<OLECHAR> strGuid;
15             strGuid.append(1,'{');
16             strGuid.append(lpsz);
17             strGuid.append(1,'}');
18             hr=CLSIDFromString((LPOLESTR)strGuid.c_str(),&guid);
19         }
20         assert(hr==S_OK);
21         return guid;
22     }
23      
24     template<class Class>
25     struct _UuidTraits{
26     };
27      
28     #define _DEFINE_UUID(Class,uuid)                       \
29     template<>                                             \
30     struct _UuidTraits<Class>{                             \
31         static const GUID& Guid(){                         \
32             static GUID guid=GUIDFromString(L##uuid);      \
33             return guid;                                   \
34         }                                                  \
35     }
36      
37     #define __uuidof(Class) _UuidTraits<Class>::Guid()
38      
39     #define DEFINE_CLSID(Class,guid)                      \
40         class Class;                                      \
41         _DEFINE_UUID(Class,guid)
42      
43     #define DEFINE_IID(Interface,iid)                     \
44         struct Interface;                                 \
45         _DEFINE_UUID(Interface,iid)
46 

  这样一来,就已经模拟出一个__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组件的代价。
 

  附注:关于本文使用的C++模板的特化技术,详细请参阅C++文法方面的书籍,例如《C++ Primer》。其实这个技巧在C++标准库——STL中有一个专门的名字:traits(萃取),你可以在很多介绍STL的书籍中见到相关的介绍。



posted @ 2008-07-02 19:27 neo 阅读(146) | 评论 (0)编辑 收藏