make_self 与投影接口的过度修正陷阱

原创
alex 39分钟前 阅读数 1 #头条

make_self 与投影接口的过度修正陷阱

背景:C++/WinRT 中创建对象的两种方式

我最近翻到 Raymond Chen 在微软 The Old New Thing 博客上的一篇文章,讲的是 C++/WinRT 里 make_self 和投影接口之间的一个坑。文章 2026 年 10 月 28 日发的,标题叫《Using make_self and converting it to the projected interface》来源:Raymond Chen。

C++/WinRT 创建你自己实现的对象,有两条路。假设 Impl 是你写的实现类。如果这个类在 IDL 文件里声明过,那它就是 winrt::Namespace::implementation::ClassName,或者是工厂对象的 winrt::Namespace::factory_implementation::ClassName。如果没在 IDL 里声明,那就是你手动从 winrt::implements 派生的那个类来源:Raymond Chen。

第一条路用 make。它创建实现对象,然后返回该对象的 Windows Runtime 投影版本。如果 Impl 是手动从 winrt::implements 派生的,投影就是它实现的第一个接口。拿到投影后,你可以用 get_self(projected) 把实现对象再拿回来,访问投影里没暴露的成员来源:Raymond Chen。

第二条路用 make_self。它创建对象,但返回 winrt::com_ptr,不是投影。你可以从 com_ptr 直接访问实现对象里的东西,然后用 * 操作符转成投影类型。两条路怎么选,取决于你想先去哪儿来源:Raymond Chen。

过度修正:一个反直觉的陷阱

Raymond 用 overcorrection 这个词形容 make_self 和投影转换之间的问题。直觉上你可能会觉得,make_self 拿到 com_ptr 后想转投影就转投影,想访问实现成员就访问成员,这不是很顺吗。但问题恰恰出在这个“顺”上来源:Raymond Chen。

让我把具体场景讲清楚。假设 Impl 是从 winrt::implements 手动派生的类,投影类型是它实现的第一个接口。你用 make_self 拿到 com_ptr,然后马上用 * 把它转成投影。Raymond 指出,这可能是错误的做法。原因在于 make_self 的本来目的是让你先访问实现对象里那些非投影的公共成员,用 -> 操作符。如果你立刻转投影,等于把这个目的跳过了,这就是过度修正来源:Raymond Chen。

我没有看到 Raymond 原文里对应的具体代码示例,但从他的描述看,这个问题同时影响手动实现和 IDL 声明实现两种场景。关键是要分清 make_self 和 make 的返回类型差异,前者给你实现对象,后者给你投影。如果你 make_self 之后立即转投影,很可能不是你想要的行为来源:Raymond Chen。

社区反应与多源交叉验证

这篇文章在 Hacker News 上只拿到 1 个积分,0 条评论来源:HN。对一个微软老牌开发者写的技术博客来说,这个数字确实冷清。Raymond Chen 在 Windows 开发圈子里的资历不用多介绍,他常年写 The Old New Thing,讲的都是 Windows 开发的边角料问题。可这次,文章的技术含量和社区的反应形成了明显落差来源:HN。

这让我想到一个现象:越是细节丰富的技术问题,越难在公开社区获得关注。Raymond 的文章详细讲了 make_self 和 make 的差异,以及过度修正的风险,但 HN 上连一个评论都没有。我不知道这算不算普遍规律,但至少在这一篇上,沉默确实发生了来源:HN。

原文和 HN 的链接互相印证,讨论程度确实很低。同一篇技术文章,在专业博客和公众论坛两个平台,热度差别可以这么大。这也说明技术内容本身的价值和它获得的关注度之间,并不总成正比来源:Raymond Chen。

我的判断是,这个陷阱值得记住,但别指望它变成热门话题。C++/WinRT 的细节坑太多了,make_self 的过度修正只是其中一个。它不显眼,不代表它不存在,尤其是当你正在手动实现一个类的时候来源:Raymond Chen。


原文:

Using make_self and converting it to the projected interface · 来源:Hacker News

作者:itfan123 值班编辑 · 发布于 2026年10月29日

版权声明

所有资源都来源于爬虫采集,如有侵权请联系我们,我们将立即删除