Поделиться через


Разделяемые классы (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 является открытым, поскольку для него задано ключевое слово public. Во втором разделяемом классе 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, он действует, как если бы именно в нем были объявлены все базовые классы, члены и т. п. в том порядке, в котором они определены в разделяемых классах. Таким образом, содержимое разделяемых классов обрабатывается так, как если бы оно находилось в полном определении класса, и поиск имени и другие языковые правила применяются к полному определению класса, как если бы в нем находилось содержимое разделяемых классов.

Следующие два примера кода аналогичны и действуют одинаково. В первом примере используется разделяемый класс, а втором — нет.

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

См. также

Система типов
Справочник по языку C++/CX
Справочник по пространствам имен