Ref クラスと構造体 (C++/CX)Ref classes and structs (C++/CX)

C++/CX は、ユーザー定義のref クラスref 構造体、およびユーザー定義の値クラス値構造体をサポートしています。The C++/CX supports user-defined ref classes and ref structs, and user-defined value classes and value structs. これらのデータ構造は、C++/CX が Windows ランタイム型システムをサポートする主なコンテナーです。These data structures are the primary containers by which C++/CX supports the Windows Runtime type system. これらのコンテンツは特定の特定の規則に従ってメタデータに出力されます。これにより、Windows ランタイムのコンポーネントと、C++ または他の言語で記述されたユニバーサル Windows プラットフォームのアプリ間で渡すことができます。Their contents are emitted to metadata according to certain specific rules, and this enables them to be passed between Windows Runtime components and Universal Windows Platform apps that are written in C++ or other languages.

ref クラスまたは ref 構造体には、次のような固有の特徴があります。A ref class or ref struct has these essential features:

  • 名前空間内部で宣言される必要があり、名前空間のスコープ、およびその名前空間内で public または private のアクセシビリティを持つことができます。It must be declared within a namespace, at namespace scope, and in that namespace it may have public or private accessibility. パブリック型だけがメタデータに出力されます。Only public types are emitted to metadata. 入れ子になったパブリック 列挙型 クラスを含め、入れ子になったパブリック クラス定義は使用できません。Nested public class definitions are not permitted, including nested public enum classes. 詳細については、「名前空間と型の可視性」を参照してください。For more information, see Namespaces and Type Visibility.

  • Ref クラス、値クラス、ref 構造体、値構造体、null 許容値構造体など、C++/CX のメンバーとして含まれる場合があります。It may contain as members C++/CX including ref classes, value classes, ref structs, value structs, or nullable value structs. また、、などのスカラー型が含まれている場合もあり float64 bool ます。It may also contain scalar types such as float64, bool, and so on. また、パブリックでない限り std::vector やカスタム クラスなどの標準の C++ 型が含まれる場合もあります。It may also contain standard C++ types such as std::vector or a custom class, as long as they are not public. C++/cx コンストラクトは public 、、 protectedinternalprivate 、またはアクセシビリティを持つことができ protected private ます。C++/CX constructs may have public, protected, internal, private, or protected private accessibility. またはのすべての public protected メンバーは、メタデータに出力されます。All public or protected members are emitted to metadata. 標準 C++ 型には private 、、 internal 、またはアクセシビリティが必要です protected private 。これにより、メタデータに出力されるのを防ぐことができます。Standard C++ types must have private, internal, or protected private accessibility, which prevents them from being emitted to metadata.

  • 1 つ以上の インターフェイス クラス または インターフェイス構造体を実装することができます。It may implement one or more interface classes or interface structs.

  • 1 つの基底クラスから継承することができ、基底クラス自体に追加の制限があります。It may inherit from one base class, and base classes themselves have additional restrictions. パブリック ref クラス階層構造での継承には、private ref クラスでの継承によりも多くの制限があります。Inheritance in public ref class hierarchies has more restrictions than inheritance in private ref classes.

  • generic として宣言することはできません。It may not be declared as generic. private アクセシビリティがある場合、テンプレートになることができます。If it has private accessibility, it may be a template.

  • その有効期間は、自動参照カウントによって管理されます。Its lifetime is managed by automatic reference counting.

宣言Declaration

次のコード片は Person ref クラスを宣言します。The following code fragment declares the Person ref class. std::mapプライベートメンバーでは標準 C++ 型が使用されており、Windows ランタイム IMapView インターフェイスがパブリックインターフェイスで使用されていることに注意してください。Notice that the standard C++ std::map type is used in the private members, and the Windows RuntimeIMapView interface is used in the public interface. また、"^" が参照型の宣言に追加されることにも注意してください。Also notice that the "^" is appended to declarations of reference types.

// #include <map>
namespace WFC = Windows::Foundation::Collections;
namespace WFM = Windows::Foundation::Metadata;

[WFM::WebHostHidden]
ref class Person sealed
{
public:
    Person(Platform::String^ name);
    void AddPhoneNumber(Platform::String^ type, Platform::String^ number);
    property WFC::IMapView<Platform::String^, Platform::String^>^ PhoneNumbers
    { 
        WFC::IMapView<Platform::String^, Platform::String^>^ get();
    }
private:
    Platform::String^ m_name;
    std::map<Platform::String^, Platform::String^> m_numbers;
};

実装Implementation

このコード例は、 Person ref クラスの実装を示しています。This code example shows an implementation of the Person ref class:

#include <collection.h>
using namespace Windows::Foundation::Collections;
using namespace Platform;
using namespace Platform::Collections;

Person::Person(String^ name): m_name(name) { }
void Person::AddPhoneNumber(String^ type, String^ number)
{
    m_numbers[type] = number;
}
IMapView< String^, String^>^ Person::PhoneNumbers::get()
{
    // Simple implementation. 
    return ref new MapView< String^, String^>(m_numbers);
}

使用法Usage

次のコード例は、クライアント コードで Person ref クラスを使用する方法を示しています。The next code example shows how client code uses the Person ref class.

using namespace Platform;

Person^ p = ref new Person("Clark Kent");
p->AddPhoneNumber("Home", "425-555-4567");
p->AddPhoneNumber("Work", "206-555-9999");
String^ workphone = p->PhoneNumbers->Lookup("Work");

また、スタック セマンティクスを使用して ref クラスのローカル変数を宣言することもできます。You can also use stack semantics to declare a local ref class variable. メモリはまだ動的に割り当てられますが、このようなオブジェクトはスタック ベースの変数のように動作します。Such an object behaves like a stack-based variable even though the memory is still allocated dynamically. 1 つの重要な違いは、スタック セマンティクスを使用して宣言されている変数に追跡参照 (%) を割り当てることができないことです。これにより、関数が終了したときに参照カウントが必ず 0 にデクリメントされます。One important difference is that you cannot assign a tracking reference (%) to a variable that is declared by using stack semantics; this guarantees that the reference count is decremented to zero when the function exits. この例では、基本 ref クラス Uri、およびスタック セマンティクスでそれを使用する関数を示します。This example shows a basic ref class Uri, and a function that uses it with stack semantics:

void DoSomething()
{
    Windows::Foundation::Uri docs("http://docs.microsoft.com");
    Windows::Foundation::Uri^ devCenter = docs.CombineUri("/windows/");
    // ... 
} // both variables cleaned up here.

メモリ管理Memory management

Ref クラスは、キーワードを使用して動的メモリに割り当て ref new ます。You allocate a ref class in dynamic memory by using the ref new keyword.

MyRefClass^ myClass = ref new MyRefClass();

オブジェクトへのハンドル演算子 ^hatと呼ばれ、基本的には C++ スマートポインターです。The handle-to-object operator ^ is known as a hat and is fundamentally a C++ smart pointer. 最後の hat がスコープ外に出るか、明示的にに設定されると、その参照先のメモリは自動的に破棄され nullptr ます。The memory it points to is automatically destroyed when the last hat goes out of scope or is explicitly set to nullptr.

定義上、ref クラスには、参照セマンティクスがあります。By definition, a ref class has reference semantics. ref クラスの変数を代入した場合、代入されるのはコピーされるハンドルであり、オブジェクト自体ではありません。When you assign a ref class variable, it's the handle that's copied, not the object itself. 次の例では、代入後に myClassmyClass2 の両方が同じメモリ位置を指します。In the next example, after assignment, both myClass and myClass2 point to the same memory location.

MyRefClass^ myClass = ref new MyRefClass();
MyRefClass^ myClass2 = myClass;

C++/CX ref クラスをインスタンス化する場合、コンストラクターを呼び出す前にメモリがゼロ初期化されます。したがって、プロパティを含む個々のメンバーをゼロ初期化する必要はありません。When a C++/CX ref class is instantiated, its memory is zero-initialized before its constructor is called; therefore it is not necessary to zero-initialize individual members, including properties. C++/CX クラスが Windows ランタイム C++ ライブラリ (WRL) クラスから派生している場合、C++/CX 派生クラスの部分だけがゼロ初期化されます。If the C++/CX class derives from a Windows Runtime C++ Library (WRL) class, only the C++/CX derived class portion is zero-initialized.

メンバーMembers

Ref クラスには public 、、、およびの各関数メンバーを含めることができます protected privatepublic とのメンバーだけ protected がメタデータに出力されます。A ref class can contain public, protected, and private function members; only public and protected members are emitted into metadata. 入れ子になったクラスと ref クラスは許可されますが、にすることはできません publicNested classes and ref classes are permitted but cannot be public. public フィールドは使用できません。public データ メンバーはプロパティとして宣言する必要があります。Public fields are not allowed; public data members must be declared as properties. プライベートまたはプロテクトの内部データ メンバーは、フィールドである場合があります。Private or protected internal data members may be fields. 既定では、ref クラスでは、すべてのメンバーのアクセシビリティは private です。By default in a ref class, the accessibility of all members is private.

Ref 構造体は ref クラスと同じですが、既定では、そのメンバーにアクセシビリティがある点が異なり public ます。A ref struct is the same as a ref class, except that by default its members have public accessibility.

public Ref クラスまたは ref 構造体はメタデータに出力されますが、他のユニバーサル Windows プラットフォームアプリおよび Windows ランタイムコンポーネントから使用できるようにするには、少なくとも1つのパブリックコンストラクターまたはプロテクトコンストラクターが必要です。A public ref class or ref struct is emitted in metadata, but to be usable from other Universal Windows Platform apps and Windows Runtime components it must have at least one public or protected constructor. パブリックコンストラクターを持つパブリック ref クラスは、 sealed アプリケーションバイナリインターフェイス (ABI) を介してさらに派生されることを防ぐためにとしても宣言する必要があります。A public ref class that has a public constructor must also be declared as sealed to prevent further derivation through the application binary interface (ABI).

const Windows ランタイム型システムで const がサポートされていないため、パブリックメンバーをとして宣言することはできません。Public members may not be declared as const because the Windows Runtime type system does not support const. 静的なプロパティを使用して、定数値を持つパブリック データ メンバーを宣言することができます。You can use a static property to declare a public data member with a constant value.

public の ref クラスまたは構造体が定義されると、コンパイラは必要な属性をクラスに適用し、その情報をアプリの .winmd ファイルに格納します。When you define a public ref class or struct, the compiler applies the required attributes to the class and stores that information in the .winmd file of the app. ただし、パブリックに封印されていない ref クラスを定義する場合は、属性を手動で適用し Windows::Foundation::Metadata::WebHostHidden て、クラスが JavaScript で記述されたユニバーサル Windows プラットフォームアプリに表示されないようにします。However, when you define a public unsealed ref class, manually apply the Windows::Foundation::Metadata::WebHostHidden attribute to ensure that the class is not visible to Universal Windows Platform apps that are written in JavaScript.

Ref クラスは、型を含む標準 C++ 型を const private 、、、またはのいずれかのメンバーに持つことができ internal protected private ます。A ref class can have standard C++ types, including const types, in any private, internal, or protected private members.

型パラメーターを持つパブリック ref クラスは許可されません。Public ref classes that have type parameters are not permitted. ユーザー定義の generic ref クラスは許可されません。User-defined generic ref classes are not permitted. private、internal、または protected private の ref クラスは、テンプレートになることができます。A private, internal, or protected private ref class may be a template.

デストラクターDestructors

C++/CX では、パブリックデストラクターでを呼び出すと、 delete オブジェクトの参照カウントに関係なくデストラクターが呼び出されます。In C++/CX, calling delete on a public destructor invokes the destructor regardless of the object's reference count. この動作により、非 RAII リソースのカスタム クリーンアップを確定的な方法で実行できるデストラクターを定義できます。This behavior enables you to define a destructor that performs custom cleanup of non-RAII resources in a deterministic manner. ただし、この場合でも、オブジェクト自体はメモリから削除されません。However, even in this case, the object itself is not deleted from memory. オブジェクトのメモリは、参照カウントがゼロに達した場合のみ解放されます。The memory for the object is only freed when the reference count reaches zero.

クラスのデストラクターがパブリックでない場合は、参照カウントがゼロに達する場合にのみ、このデストラクターが呼び出されます。If a class's destructor is not public, then it is only invoked when the reference count reaches zero. deleteプライベートデストラクターを持つオブジェクトに対してを呼び出すと、コンパイラによって警告 C4493 が発生します。これは、のデストラクターに " <type name> public" アクセシビリティがないため、"delete 式は効果がありません" という意味です。If you call delete on an object that has a private destructor, the compiler raises warning C4493, which says "delete expression has no effect as the destructor of <type name> does not have 'public' accessibility."

Ref クラスのデストラクターでは、次以外の宣言はできません。Ref class destructors can only be declared as follows:

  • public および virtual (sealed または unsealed 型で使用できます)public and virtual (allowed on sealed or unsealed types)

  • protected private と non-virtual (unsealed 型でのみ使用できます)protected private and non-virtual (only allowed on unsealed types)

  • private と non-virtual (sealed 型でのみ使用できます)private and non-virtual (allowed only on sealed types)

アクセシビリティ、仮想性、およびシールド性のこれ以外の組み合わせは使用できません。No other combination of accessibility, virtualness, and sealedness is allowed. デストラクターが明示的に宣言されない場合、型の基底クラスまたはメンバーに public デストラクターがあると、コンパイラは public virtual デストラクターを生成します。If you do not explicitly declare a destructor, the compiler generates a public virtual destructor if the type's base class or any member has a public destructor. それ以外の場合、コンパイラは unsealed 型には protected private non-virtual デストラクター、sealed 型には private non-virtual デストラクターを生成します。Otherwise, the compiler generates a protected private non-virtual destructor for unsealed types, or a private non-virtual destructor for sealed types.

デストラクターを既に実行しているクラスのメンバーにアクセスを試みたときの動作は不確定です。プログラムがクラッシュする可能性が高いと思われます。The behavior is undefined if you try to access members of a class that has already had its destructor run; it will most likely cause the program to crash. public デストラクターがない型上で delete t を呼び出しても、何の効果もありません。Calling delete t on a type that has no public destructor has no effect. delete this型階層内から既知のまたはデストラクターを持つ型または基底クラスに対してを呼び出すと、何 private protected private も効果がありません。Calling delete this on a type or base class that has a known private or protected private destructor from within its type hierarchy also has no effect.

public デストラクターが宣言されると、コンパイラがコードを生成するので、ref クラスが Platform::IDisposable を実装し、デストラクターが Dispose メソッドを実装します。When you declare a public destructor, the compiler generates the code so that the ref class implements Platform::IDisposable and the destructor implements the Dispose method. Platform::IDisposableは、の C++/CX 投影です Windows::Foundation::IClosablePlatform::IDisposable is the C++/CX projection of Windows::Foundation::IClosable. これらのインターフェイスは、明示的に実装しないでください。Never explicitly implement these interfaces.

継承Inheritance

Platform::Object は、すべての ref クラスの汎用基底クラスです。Platform::Object is the universal base class for all ref classes. ref クラスは、いずれも Platform::Object に暗黙的に変換可能で、 Object::ToStringをオーバーライドできます。All ref classes are implicitly convertible to Platform::Object and can override Object::ToString. ただし、Windows ランタイム継承モデルは、一般的な継承モデルとしては想定されていません。C++/CX では、ユーザー定義のパブリック ref クラスは基底クラスとして機能できません。However, the Windows Runtime inheritance model not intended as a general inheritance model; in C++/CX this means that a user-defined public ref class cannot serve as a base class.

XAML ユーザー コントロールを作成し、オブジェクトが依存関係プロパティ システムに参加している場合は、 Windows::UI::Xaml::DependencyObject を基底クラスとして使用できます。If you are creating a XAML user control, and the object participates in the dependency property system, then you can use Windows::UI::Xaml::DependencyObject as a base class.

MyBase から継承する unsealed クラス DependencyObjectが定義されると、コンポーネントまたはアプリ内の他の public または private の ref クラスは MyBaseから継承できるようになります。After you have defined an unsealed class MyBase that inherits from DependencyObject, other public or private ref classes in your component or app may inherit from MyBase. public ref クラスの継承は、仮想メソッド、ポリモーフィック ID、およびカプセル化のオーバーライドをサポートする目的以外には実行しないでください。Inheritance in public ref classes should only be done to support overrides of virtual methods, polymorphic identity, and encapsulation.

private 基本 ref クラスがなくても、既存の unsealed クラスから派生できます。A private base ref class is not required to derive from an existing unsealed class. 独自のプログラム構造をモデル化するかまたはコードの再利用を有効にするために、オブジェクト階層構造を必要とする場合は、private または internal の ref クラスを使用するか、さらに優れた手法として標準 C++ クラスを使用してください。If you require an object hierarchy to model your own program structure or to enable code reuse, then use private or internal ref classes, or better yet, standard C++ classes. public sealed ref クラス ラッパーを通じて、プライベート オブジェクト階層構造の機能を公開できます。You can expose the functionality of the private object hierarchy through a public sealed ref class wrapper.

C++/CX で public または protected コンストラクターを持つ ref クラスは、sealed として宣言する必要があります。A ref class that has a public or protected constructor in C++/CX must be declared as sealed. この制限は、C# や Visual Basic などの他の言語で記述されたクラスが、C++/cxで記述された Windows ランタイムコンポーネントで宣言する型から継承する方法がないことを意味します。This restriction means that there is no way for classes that are written in other languages such as C# or Visual Basic to inherit from types that you declare in a Windows Runtime component that's written in C++/CX.

C++/CX での継承に関する基本的な規則を次に示します。Here are the basic rules for inheritance in C++/CX:

  • ref クラスは多くても 1 つの基本 ref クラスからしか直接継承できませんが、任意の数のインターフェイスを実装できます。Ref classes can inherit directly from at most one base ref class, but can implement any number of interfaces.

  • あるクラスに public コンストラクターがある場合、さらに派生されることを防ぐために sealed として宣言する必要があります。If a class has a public constructor, it must be declared as sealed to prevent further derivation.

  • 基底クラスが Windows::UI::Xaml::DependencyObjectなどの既存の unsealed 基底クラスから直接または間接的に派生する場合は、internal または protected private のコンストラクターを持つ public unsealed 基底クラスを作成できます。You can create public unsealed base classes that have internal or protected private constructors, provided that the base class derives directly or indirectly from an existing unsealed base class such as Windows::UI::Xaml::DependencyObject. .winmd ファイル間でのユーザー定義 ref クラスの継承はサポートされません。ただし、ref クラスは別の .winmd ファイルで定義されているインターフェイスから継承できます。Inheritance of user-defined ref classes across .winmd files is not supported; however, a ref class can inherit from an interface that's defined in another .winmd file. ユーザー定義の基本 ref クラスの派生クラスは、同じ Windows ランタイムコンポーネントまたはユニバーサル Windows プラットフォームアプリ内でのみ作成できます。You can create derived classes from a user-defined base ref class only within the same Windows Runtime component or Universal Windows Platform app.

  • ref クラスの場合、パブリック継承のみサポートされます。For ref classes, only public inheritance is supported.

    ref class C{};
    public ref class D : private C //Error C3628
    {};
    

次の例では、継承階層構造の他の ref クラスから派生する public ref クラスを公開する方法を示します。The following example shows how to expose a public ref class that derives from other ref classes in an inheritance hierarchy.

namespace InheritanceTest2 
{
    namespace WFM = Windows::Foundation::Metadata;

    // Base class. No public constructor.
    [WFM::WebHostHidden]
    public ref class Base : Windows::UI::Xaml::DependencyObject
    {
    internal:
        Base(){}
    protected:
        virtual void DoSomething (){}
        property Windows::UI::Xaml::DependencyProperty^ WidthProperty;
    };

    // Class intended for use by client code across ABI.
    // Declared as sealed with public constructor.
    public ref class MyPublicClass sealed : Base
    {
    public:
        MyPublicClass(){}
        //...
    };
}

関連項目See also

型システムType System
値クラスと構造体Value classes and structs
C++/CX 言語リファレンスC++/CX Language Reference
名前空間のリファレンスNamespaces Reference