Raymond Chen 解释了如何重新理解 C++/WinRT 实现类型中的 C++ 访问限定符:由于实现类型只对生成它们的模块可见,public 对应实现的接口成员、protected 用于派生类、private 仅限本类,并说明了 IDL 编译器自动生成 WidgetT 模板的机制。
<p>In C++/WinRT, Windows Runtime classes are exposed to the outside world through the projection, but internally they are represented by their implementation type. Since the outside world sees only the projection, implementation types are visible only to the module that produced them.</p>
<p>This realization lets you reinterpret the C++ access specifiers for C++/WinRT implementation types.</p>
<table class="cp3" style="border-collapse: collapse;" border="1" cellspacing="0" cellpadding="3">
<tbody>
<tr>
<th>Declared on<br />
implementation as</th>
<th>C# and C++/CX<br />
equivalent</th>
<th>Accessible to</th>
</tr>
<tr>
<td>implemented interface</td>
<td><tt>public</tt></td>
<td>Anyone</td>
</tr>
<tr>
<td><tt>public</tt></td>
<td><tt>internal</tt></td>
<td>Code in the same module</td>
</tr>
<tr>
<td><tt>protected</tt></td>
<td><tt>protected</tt></td>
<td>Code in derived classes</td>
</tr>
<tr>
<td><tt>private</tt></td>
<td><tt>private</tt></td>
<td>Code in the same class</td>
</tr>
</tbody>
</table>
<p>In code:</p>
<pre>struct Widget : winrt::implements<Widget, IStringable>
{
public:
// This is a member of IStringable,
// so it is accessible to anyone.
winrt::hstring ToString();
// This does not implement any member from IStringable,
// so it is accessible to other code in the same module.
void Recolor(winrt::Windows::UI::Color newColor);
protected:
// Accessible to implementation classes that derive from Widget.
void Reverse();
private:
// Accessible only to Widget itself.
void Reset();
};
</pre>
<p>Note that if you are implementing a runtime class, then C++/WinRT autogenerates a template for you that auto-declares all of the declared interfaces of that class.</p>
<pre>// Widget.idl
namespace Contoso
{
runtimeclass Widget : Windows.Foundation.IStringable
{
String Name{ get; };
void Toggle();
}
}
</pre>
<p>The IDL compiler autogenerates an interface <code>IWidget</code> with a property <code>Name</code> and a method <code>Toggle()</code>.</p>
<pre>// implementation
namespace winrt::Contoso
{
struct Widget : <span style="border: solid 1px currentcolor;">WidgetT<Widget></span>
{
⟦ ... ⟧
};
}
</pre>
<p>The <code>WidgetT<Widget></code> expands to <code>implements<Widget, IWidget, Windows::Foundation::IStringable></code> because those are the interfaces declared by the IDL file.</p>
<p>The post <a href="https://devblogs.microsoft.com/oldnewthing/20261009-00/?p=112764/">One way of thinking about access specifiers in C++/WinRT implementation types</a> appeared first on <a href="https://devblogs.microsoft.com/oldnewthing">The Old New Thing</a>.</p>
# One way of thinking about access specifiers in C++/WinRT implementation types - The Old New Thing
Source: [https://devblogs.microsoft.com/oldnewthing/20261009-00/?p=112764/](https://devblogs.microsoft.com/oldnewthing/20261009-00/?p=112764/)
In C\+\+/WinRT, Windows Runtime classes are exposed to the outside world through the projection, but internally they are represented by their implementation type\. Since the outside world sees only the projection, implementation types are visible only to the module that produced them\.
This realization lets you reinterpret the C\+\+ access specifiers for C\+\+/WinRT implementation types\.
Declared on
implementation asC\# and C\+\+/CX
equivalentAccessible toimplemented interfacepublicAnyonepublicinternalCode in the same moduleprotectedprotectedCode in derived classesprivateprivateCode in the same classIn code:
```
struct Widget : winrt::implements<Widget, IStringable>
{
public:
// This is a member of IStringable,
// so it is accessible to anyone.
winrt::hstring ToString();
// This does not implement any member from IStringable,
// so it is accessible to other code in the same module.
void Recolor(winrt::Windows::UI::Color newColor);
protected:
// Accessible to implementation classes that derive from Widget.
void Reverse();
private:
// Accessible only to Widget itself.
void Reset();
};
```
Note that if you are implementing a runtime class, then C\+\+/WinRT autogenerates a template for you that auto\-declares all of the declared interfaces of that class\.
```
// Widget.idl
namespace Contoso
{
runtimeclass Widget : Windows.Foundation.IStringable
{
String Name{ get; };
void Toggle();
}
}
```
The IDL compiler autogenerates an interface`IWidget`with a property`Name`and a method`Toggle\(\)`\.
```
// implementation
namespace winrt::Contoso
{
struct Widget : WidgetT<Widget>
{
⟦ ... ⟧
};
}
```
The`WidgetT<Widget\>`expands to`implements<Widget, IWidget, Windows::Foundation::IStringable\>`because those are the interfaces declared by the IDL file\.
### Category
### Topics
## Author

Raymond has been involved in the evolution of Windows for more than 30 years\. In 2003, he began a Web site known as The Old New Thing which has grown in popularity far beyond his wildest imagination, a development which still gives him the heebie\-jeebies\. The Web site spawned a book, coincidentally also titled The Old New Thing \(Addison Wesley 2007\)\. He occasionally appears on the Windows Dev Docs Twitter account to tell stories which convey no useful information\.
A Lobsters discussion exploring whether Rust (or future languages) should add a `read` visibility modifier for struct fields, allowing public read access without public write access, and asking about hidden language-design gotchas and sensible defaults.
Raymond Chen continues his series on building an agile Windows Runtime delegate in C++/WinRT, comparing how C++/WinRT, C++/CX, and WRL handle non-marshalable delegates and agile reference creation.
The article discusses a fix for exception safety in C++/WinRT when creating an agile delegate, addressing the issue of unspecified lambda capture construction order to prevent reference leaks.