21.Refクラス
ネイティブ・クラスと同様に、ref クラスはフィールド、メンバ関数、そして、ネスト型を含むことができます。
しかしながら、ネイティブ・クラスとは違って、ref クラスはガベージ・コレクションを含む CLI の特徴の全ての利点を駆使することができます。
21.1 refクラス宣言
ref クラスは
class-key(クラス・キー) ref class もしくは、ref struct で定義されるクラスです。
ref class 定義と ref struct 定義はメンバへのデフォルトのアクセス可能性が違います。
デフォルトでは、ref class のメンバは private であり、ref struct のメンバは public です。
ref クラスの定義は
attributes(属性)(
§29 )、
top-level-visibility(上層型識別)(
§12.4 )、
class-modifiers(クラス修飾子)(
§19.1.1 )、そして、
base-clause(基底節)(
§21.1.1 )のセットを含むことができます。
ref クラスの定義はネイティブ・クラス定義の内部にネストすることができます。しかしながら、ネイティブ・クラス定義は ref クラス定義の中にネストするべきではありません。
メタデータの詳細は
§34.7.1 を参照のこと。
21.1.1 refクラス基底仕様
ref クラス定義は ref クラスの直接的な基底クラスとその ref クラスによって実装されるべきインターフェイスを定義する
base-clause(基底節)を含むことができます。
もし、
base-specifier(基底指定子)が
access-specifier(アクセス指定子)を含んでいれば、その
access-specifier(アクセス指定子)は public であるべきです。
もし、
base-specifier(基底指定子)が
access-specifier(アクセス指定子)を含んでいなければ、たとえその ref クラスが ref class キーワードで定義されていたとしても、その
access-specifier(アクセス指定子)は暗黙のうちに public となります。
ref クラス型はその直接的な基底としておおむね一つのクラスを持つべきであり、そのクラス型は ref クラス型であるべきです。
もし、直接的な基底クラスが指定されなければ、直接基底クラスは System::Object です。
ref クラス型の直接基底クラスはネイティブ・クラス、sealed ref クラス、また、次の型のどれかであるべきではありません:System::Array, System::Delegate, System::Enum, または、System::ValueType。
ref クラス型の直接基底クラスは少なくとも ref クラス型自身と同じアクセス可能性を持つべきです。
もし、ref クラス定義がインターフェイス型を指定する一つ以上の
base-specifier(基底指定子)を含む場合、その ref クラスはそれらのインターフェイス型を実装することを告げています。
(インターフェイスの実装については
§25.3 でさらに議論します。)
21.2 refクラスメンバ
ref クラスのメンバはその
member-specification(メンバ規定)によって導入された全てのメンバと、直接基底クラスから継承されたメンバによって構成されます。
ref クラスはその型がネイティブ配列かネイティブ・クラスであるメンバを含むべきではありません。
[注意:そのような型のメンバを許すのは混合型(
§23 )を親の型とするものです。]
ref クラスはビット・フィールドとなるメンバを含むべきではありません。
ref クラスは friend を宣言するべきではありません。
ref クラスは任意のアクセス宣言を含むべきではありません。
いくつかの ref クラスメンバ宣言、メンバ・アクセス、そして、メンバ関数はメタデータ生成の間、特殊なハンドリングを必要とします。
さらなる情報は
§34.9 を参照のこと。
21.2.1 変数の初期化
標準C++(§8.5/5)の
zero-initialize(0値初期化)の定義は以下のように拡張されます。
型 T のオブジェクトを0値初期化すると言うことは:
- もし、T がハンドル型であれば、そのオブジェクトは T に変換されたヌル値定数の値にセットされます。
- もし、T がハンドル型以外のスカラー型であれば、そのオブジェクトの値は T 型に変換された 0 の値にセットされます。
- ...
標準C++(§8.5/9)に記述されているデフォルト初期値は以下のように拡張されています。
もし、オブジェクトに初期化子が指定されなければ、そして、オブジェクトが(可能であれば cv-qualifiedな)非PODクラス型(か、その配列)であれば、オブジェクトはデフォルト初期化されるべきでしょう。
もし、オブジェクトが const-qualified 型であれば、その背景となるクラス型はユーザー宣言デフォルト・コンストラクタを持つべきです。
もし、ハンドルに初期化子が指定されていなければ、ハンドルは常に0値初期化されるべきです。
そうでなく、もし、非静的オブジェクトに初期化子が指定されていなければ、オブジェクトとそのサブオブジェクトは、いずれにせよ、不定の初期値を持ちます。もし、オブジェクトやその何らかのサブオブジェクトが const-qualified 型であれば、そのプログラムは不正です。
[根拠:ハンドルは、それらがガベージ・コレクタの根底に使われるので、常に適切な値を持っていなければなりません。
もし、ハンドルが不適切な値を持っていたら、ランタイムは失敗するでしょう。
それ故、初期化されていないハンドルはランタイム失敗をさけるために常に0です。]
標準C++ 参照と同様に、追跡参照は常に初期化済みであるべきです。
ref クラス・インスタンスのデフォルト値は、値型フィールドはそのデフォルト値に、そして、全てのハンドル型フィールドは nullptr にセットされます。
21.3 関数
ref クラス中の仮想メンバ関数宣言は次のものを含みます。
- function-modifier(関数修飾子) abstract (§19.4.3 )
- function-modifier(関数修飾子) new (§19.4.4 )
- function-modifier(関数修飾子) override, ないし、override-specifier(上書き指定子), もしくはその両方(§19.4.1 )
- function-modifier(関数修飾子) sealed (§19.4.2 )
ref クラス中の上書き仮想関数は違う返却型を持つべきではありません。
[根拠:これは CLI によって課せられた制限です。]
ref クラスのメンバ関数は
cv-qualified-seqを持つべきではありません。
ref クラス中のメンバ関数はオプションとしてその
parameter-declaration-clause(パラメータ宣言節)に
parameter-array(パラメータ配列)(
§18.4 )を持つことができます。
[注意:ref クラスのそれぞれについて、その実装はいくつかの名前を予約済みです。(
§19.2.3 )]
ref クラスのメンバ関数はローカル・クラスを含むべきではありません。
[注意:ref クラスのメンバ関数は hidebysig 名前検索(
§10.7 )を使います。]
21.4 プロパティ
refクラスはプロパティ(
§19.5 )をサポートします。
[注意:各々のプロパティ定義ごとに、実装にいくつかの名前が予約されています(
§19.2.1 )。]
21.5 イベント
refクラスはイベント(
§19.6 )をサポートします。
[注意:各々のイベント定義ごとに、実装にいくつかの名前が予約されています(
§19.2.2 )。]
21.6 静的演算子
refクラスは静的演算子(
§19.7 )をサポートします。
21.7 非静的演算子
デフォルトとして、refクラスはコピー代入演算子を持っていません。
もし、必要となれば、コピー代入演算子は明示的に定義されるべきでしょう。
21.8 インスタンス・コンストラクタ
デフォルトとして、refクラスはコピー・コンストラクタを持ちません。
もし、必要となれば、明示的に定義されるべきでしょう。
21.9 静的コンストラクタ
refクラスは静的コンストラクタ(
§19.10 )をサポートします。
refクラスや値クラスの静的コンストラクタはそのクラスが発生する際にどんな静的メンバも最初に参照される前に、実行されます。
21.10 リテラル・フィールド
refクラスはリテラル・フィールド(
§19.11 )をサポートします。
21.11 initonly フィールド
refクラスは initonly フィールド(
§19.12 )をサポートします。
21.12 デストラクタとファイナライザ
refクラスはデストラクタとファイナライザ(
§19.13 )の定義を含むことができます。
21.13 デリゲート型
refクラスは
delegate-specifiers(デリゲート指定子)(
§27.1 )をサポートします。
refクラスはデリゲート型を持つフィールドを含むことが許されています。