Redigera

Dela via


Partial classes (C++/CX)

A partial class is a construct that supports scenarios in which you are modifying one part of a class definition, and automatic code-generating software—for example, the XAML designer—is also modifying code in the same class. By using a partial class, you can prevent the designer from overwriting your code. In a Visual Studio project, the partial modifier is applied automatically to the generated file.

Syntax

To define a partial class, use the partial keyword immediately before the class-key of what would otherwise be a normal class definition. A keyword such as partial ref class is a contextual keyword that contains whitespace characters. Partial definitions are supported in the following constructs.

  • class or struct

  • ref class or ref struct

  • value class or value struct

  • enum or enum class

  • ref interface, interface class, interface struct, or __interface

  • union

This example demonstrates a partial ref class:

partial ref class MyClass {/* ... */};

Contents

A partial class definition can contain anything that the full class definition can contain if the partial keyword had been omitted. With one exception, this includes any valid construct such as base classes, data members, member functions, enums, friend declarations, and attributes. And inline definitions of static data members are permitted.

The one exception is class accessibility. For example, the statement public partial class MyInvalidClass {/* ... */}; is an error. Any access specifiers that are used in a partial class definition for MyInvalidClass don't affect the default accessibility in a subsequent partial or full class definition for MyInvalidClass.

The following code fragment demonstrates accessibility. In the first partial class, Method1 is public because its accessibility is public. In the second partial class, Method2 is private because the default class accessibility is private.

partial ref class N 
{
public:
    int Method1(); // Method1 is public.

};
ref class N 
{   
    void Method2(); // Method2 is private.
};

Declaration

A partial definition of a class such as MyClass is only a declaration of MyClass. That is, it only introduces the name MyClass. MyClass can't be used in a way that requires a class definition, for example, knowing the size of MyClass or using a base or member of MyClass. MyClass is considered to be defined only when the compiler encounters a non-partial definition of MyClass.

The following example demonstrates the declaration behavior of a partial class. After declaration #1, MyClass can be used as if it were written as the forward declaration, ref class MyClass;. Declaration #2 is equivalent to declaration #1. Declaration #3 is valid because it's a forward declaration to a class. But declaration #4 is invalid because

MyClass is not fully defined.

Declaration #5 does not use the partial keyword, and the declaration fully defines MyClass. Consequently, declaration #6 is valid.

// 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.

Number and ordering

There can be zero or more partial class definitions for every full definition of a class.

Every partial class definition of a class must lexically precede the one full definition of that class, but doesn't have to precede forward declarations of the class. If there's no full definition of the class, then the partial class declarations can only be forward declarations.

All class-keys such as class and struct must match. For example, it's an error to code partial class X {}; struct X {};.

The following example demonstrates number and ordering. The last partial declaration fails because the class is already defined.

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.

Full definition

At the point of the full definition of the class X, the behavior is the same as if the definition of X had declared all base classes, members, and so on, in the order in which they were encountered and defined in the partial classes. That is, the contents of the partial classes are treated as though they were written at the point of full definition of the class, and name lookup and other language rules are applied at the point of the full definition of the class as if the contents of the partial classes were written in place

The following two code examples have identical meaning and effect. The first example uses a partial class and the second example doesn't.

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);

};


Templates

A partial class can't be a template.

Restrictions

A partial class can't span beyond one translation unit.

The partial keyword is supported only in combination with the ref class keyword or the value class keyword.

Examples

The following example defines the Address class across two code files. The designer modifies Address.details.h and you modify Address.h. Only the class definition in the first file uses the partial keyword.

// 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(); }
};

See also

Type System
C++/CX Language Reference
Namespaces Reference