分部类 (C++/CX)
分部类是支持你修改一部分类定义的方案的构造,而自动代码生成软件(例如 XAML 设计器)也在修改同一个类中的代码。 通过使用分部类,可以防止设计器重写代码。 在 Visual Studio 项目中, partial
修饰符自动应用于生成的文件。
语法
若要定义分部类,请紧接在类键(不然就是一个普通类定义的类键)之前使用 partial
关键字。 关键字(如 partial ref class
)是包含空白字符的上下文关键字。 下列构造支持分部定义。
class
或struct
ref class
或ref struct
value class
或value struct
enum
或enum class
ref interface
、interface class
、interface struct
或__interface
union
此示例演示分部 ref class
:
partial ref class MyClass {/* ... */};
目录
如果省略了 partial
关键字,则分部类定义可以包含完整类定义可包含的一切。 有一个例外,其中包括所有有效构造,如基类、数据成员、成员函数、枚举、友元声明和特性。 并且允许静态数据成员的内联定义。
一个例外是类可访问性。 例如,语句 public partial class MyInvalidClass {/* ... */};
是一个错误。 MyInvalidClass 的分部类定义中使用的任何访问说明符不会影响 MyInvalidClass 后续的分部或完整类定义中的默认可访问性。
下面的代码片段演示了可访问性。 在第一个分部类中, Method1
是公共的,因为它的可访问性是公共的。 在第二个分部类中, Method2
是私有的,因为默认类可访问性是私有的。
partial ref class N
{
public:
int Method1(); // Method1 is public.
};
ref class N
{
void Method2(); // Method2 is private.
};
声明
类的分部定义(例如 MyClass
)只是 MyClass 的声明。 即,它只引入名称 MyClass
。 MyClass
不能以需要类定义的方式使用,例如,知道 MyClass
的大小或使用 MyClass
的基或成员。 仅当编译器遇到 MyClass
的非分部定义时,MyClass
才被视为已定义。
下面的示例演示分部类的声明行为。 在声明 #1 后,MyClass
可按照其被编写为前向声明 ref class MyClass;
时的方式使用。 声明 #2 等效于声明 #1。 声明 #3 是有效的,因为它是类的前向声明。 但是声明 #4 无效,因为
MyClass
未完全定义。
声明 #5 不使用 partial
关键字,并且完全定义了 MyClass
。 因此,声明 #6 是有效的。
// Declaration #1
partial ref class MyClass {};
// Declaration #2
partial ref class MyClass;
// Declaration #3
MyClass^ pMc; // OK, forward declaration.
// Declaration #4
MyClass mc; // Error, MyClass is not defined.
// Declaration #5
ref class MyClass { };
// Declaration #6
MyClass mc; // OK, now MyClass is defined.
编号和排序
类的每个完整定义可以有零个或多个分部类定义。
类的每个分部类定义在词法上都必须排在该类的一个完整定义前,但是不必排在类的前向声明前。 如果类没有完整定义,则分部类声明只能是前向声明。
所有类键(如 class
和 struct
)都必须匹配。 例如,编码 partial class X {}; struct X {};
。
下面的示例演示编号和排序。 最后一个分部声明失败,因为该类已经定义。
ref class MyClass; // OK
partial ref class MyClass{}; //OK
partial ref class MyClass{}; // OK
partial ref class MyClass{}; // OK
ref class MyClass{}; // OK
partial ref class MyClass{}; // C3971, partial definition cannot appear after full definition.
完整定义。
在类 X 的完整定义点,行为是相同的,就好像 X 的定义已按照在分部类中遇到和定义基类、成员等的顺序,声明了所有这些基类、成员等一样。 即,处理分部类的内容就好像它们是在类的完整定义点处编写的,名称查找和其他语言规则在类的完整定义点处应用,就好像分部类的内容是就地编写的
下面两个代码示例具有相同的含义和效果。 第一个示例使用分部类,第二个示例则未使用。
ref class Base1 { public: property int m_num; int GetNumBase();};
interface class Base2 { int GetNum(); };
interface class Base3{ int GetNum2();};
partial ref class N : public Base1
{
public:
/*...*/
};
partial ref class N : public Base2
{
public:
virtual int GetNum();
// OK, as long as OtherClass is
//declared before the full definition of N
void Method2( OtherClass^ oc );
};
ref class OtherClass;
ref class N : public Base3
{
public:
virtual int GetNum2();
};
ref class OtherClass;
ref class N : public Base1, public Base2, public Base3
{
public:
virtual int GetNum();
virtual int GetNum2();
private:
void Method2(OtherClass^ oc);
};
模板
分部类不能是模板。
限制
分部类不能超越一个翻译单元范围。
partial
关键字只能与 ref class
关键字或 value class
关键字组合使用。
示例
下面的示例跨两个代码文件定义 Address
类。 设计器修改 Address.details.h
,你修改 Address.h
。 只有第一个文件中的类定义使用 partial
关键字。
// Address.Details.h
partial ref class Address
{
private:
Platform::String^ street_;
Platform::String^ city_;
Platform::String^ state_;
Platform::String^ zip_;
Platform::String^ country_;
void ValidateAddress(bool normalize = true);
};
// Address.h
#include "Address.details.h"
ref class Address
{
public:
Address(Platform::String^ street, Platform::String^ city, Platform::String^ state,
Platform::String^ zip, Platform::String^ country);
property Platform::String^ Street { Platform::String^ get(); }
property Platform::String^ City { Platform::String^ get(); }
property Platform::String^ State { Platform::String^ get(); }
property Platform::String^ Zip { Platform::String^ get(); }
property Platform::String^ Country { Platform::String^ get(); }
};