{"id":104205,"date":"2020-09-11T07:00:00","date_gmt":"2020-09-11T14:00:00","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/oldnewthing\/?p=104205"},"modified":"2020-09-11T07:09:40","modified_gmt":"2020-09-11T14:09:40","slug":"20200911-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20200911-00\/?p=104205","title":{"rendered":"The macros for declaring COM interfaces, revisited: C++ implementation"},"content":{"rendered":"<p>Last time, we looked at <a title=\"The macros for declaring COM interfaces, revisited: C++ version\" href=\"https:\/\/devblogs.microsoft.com\/oldnewthing\/20200910-00\/?p=104203\"> the macros for declaring COM interfaces and how they expand when compiled for C++<\/a>. Now we&#8217;ll look at the macros you use for implementing the interface.<\/p>\n<pre>class Class : public ISomething\r\n{\r\npublic:\r\n    \/\/ *** IUnknown ***\r\n    IFACEMETHOD(QueryInterface)(REFIID riid, void** ppv);\r\n    IFACEMETHOD_(ULONG, AddRef)();\r\n    IFACEMETHOD_(ULONG, Release)();\r\n\r\n    \/\/ *** ISomething ***\r\n    IFACEMETHOD(Method1)();\r\n    IFACEMETHOD_(int, Method2)();\r\n    IFACEMETHOD(Method3)(int iParameter);\r\n};\r\n<\/pre>\n<p>The <code>IFACEMETHOD<\/code> and <code>IFACEMETHOD_<\/code> macros are used for declaring that your class implements a particular method. The result of the macro expansion is this:<\/p>\n<pre>class Class : public ISomething\r\n{\r\npublic:\r\n    \/\/ *** IUnknown ***\r\n    \/* IFACEMETHOD(QueryInterface)(REFIID riid, void** ppv); *\/\r\n    __override virtual __declspec(nothrow)\r\n    HRESULT QueryInterface(REFIID riid, void** ppv);\r\n\r\n    \/* IFACEMETHOD_(ULONG, AddRef)(); *\/\r\n    __override virtual __declspec(nothrow)\r\n    ULONG AddRef();\r\n\r\n    \/* IFACEMETHOD_(ULONG, Release)(); *\/\r\n    __override virtual __declspec(nothrow)\r\n    ULONG Release();\r\n\r\n    \/\/ *** ISomething ***\r\n    \/* IFACEMETHOD(Method1)(); *\/\r\n    __override virtual __declspec(nothrow)\r\n    HRESULT Method1();\r\n\r\n    \/* IFACEMETHOD_(int, Method2)(); *\/\r\n    __override virtual __declspec(nothrow)\r\n    int Method2();\r\n\r\n    \/* IFACEMETHOD(Method3)(int iParameter); *\/\r\n    __override virtual __declspec(nothrow)\r\n    HRESULT Method3(int iParameter);\r\n};\r\n<\/pre>\n<p>Analogous with the <code>STDMETHOD<\/code> and <code>STDMETHOD_<\/code> macros, you use the underscore version of the <code>IFACEMETHOD<\/code> macro (<code>IFACEMETHOD_<\/code>) if the return value is not <code>HRESULT<\/code>.<\/p>\n<p>The <code>__override<\/code> annotation is understood by static analysis tools like <a title=\"Prefast And SAL Annotations\" href=\"https:\/\/devblogs.microsoft.com\/cppblog\/prefast-and-sal-annotations\/\"> PREfast<\/a>. The annotation means that the static analysis tool should verify that function declaration overrides an identical method in the base class.<\/p>\n<p>The <code>__override<\/code> annotation was introduced as part of SAL, the Microsoft Standard Annotation Language. It has been made redundant by C++11&#8217;s <code>override<\/code> keyword, but the macros still generate them just the same.<\/p>\n<p>In practice, therefore, you are probably going to write<\/p>\n<pre>    IFACEMETHOD(Method1)() override;\r\n<\/pre>\n<p>to inform both the static analysis tool and the C++ compiler of your intention to override a method from the base class.<\/p>\n<p>When it comes time to define the method, you do it with the <code>IFACEMETHODIMP<\/code> macro:<\/p>\n<pre>IFACEMETHODIMP Class::Method1()\r\n{\r\n    ...\r\n}\r\n<\/pre>\n<p>Use <code>IFACEMETHODIMP_(T)<\/code> if the return type is not <code>HRESULT<\/code>.<\/p>\n<p>The above expands to<\/p>\n<pre>__override HRESULT __stdcall Class::Method1()\r\n{\r\n    ...\r\n}\r\n<\/pre>\n<p>If you want to implement the method inline, then you can put the implementation directly after the declaration inside the class definition.<\/p>\n<pre>class Class : public ISomething\r\n{\r\npublic:\r\n    ...\r\n    IFACEMETHOD(Method1)() override { ... }\r\n    ...\r\n};\r\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Now to make things concrete.<\/p>\n","protected":false},"author":1069,"featured_media":111744,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[25],"class_list":["post-104205","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>Now to make things concrete.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/104205","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/users\/1069"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/comments?post=104205"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/104205\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media\/111744"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media?parent=104205"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=104205"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=104205"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}