* ユーザー定義型 [#u10b9718] #contents * 概要 [#k79548b7] |項目|pod|struct|class|interface|utility|h |デフォルトコンストラクタのユーザー定義|x *1|x *1|o|x|x| |コンストラクタ|o|o|o|x|x| |デストラクタ|x|o|o|x|x| |静的コンストラクタ&br;静的デストラクタ|o|o|o|x|o| |メンバ変数|o|o|o|x|x| |structメンバ変数|x|o|o|x|x| |objectメンバ変数|x|o|o|x|x| |メンバ関数|o|o|o|o|x| |ガベージコレクタ対象|x|x|o|o|x| |インターフェースの継承|x|x|o|o|x| |公開修飾子(public/private)|o|o|o|x|o| |代入オーバーロード|x|o|x|x|x| |>|>|>|>|>|ver2.0| |invariant|o|o|o|x|x| |scope属性|x|x|o|x|x| |inlineメンバ変数|o|o|o|x|x| *1 : 全部0(規定値)で初期化。 structでも許さない理由は,static変数にstructな変数を定義すると,初期化時に関数コールが走ってしまうため。 関数コールは.init初期化が終わった後から呼び出すように統一したい。 ** interface [#s160dc18] - C#,Dのinterfaceと同じ - interfaceは複数にinterfaceを継承することができる #code(c,){{ interface IButtonListener { // 継承したクラスは必ず実装する必要がある。 void onButtonPush( in IButton sender )const; }; }} ** class [#gcd95ad1] - 強制的にobject型を継承している - DやC#のように1つだけの継承できるはできる。多重継承はできない。 - interfaceは何個でも継承できる ** pod [#y7b8ef47] - plain object data - C言語のstructに近い - デフォルトコンストラクタはオブジェクトのメモリ領域を0で初期化する扱いになる ** struct [#g20f0c14] - 継承のないC++のクラス・D言語のscope classと同じ - ガベージコレクト対象ではないので,structなオブジェクトをnewしそのインスタンスの参照を保持することができない ** utility [#maa1e0a9] - static関数のみ提供する型,インスタンスを作ることができない。 * メンバ公開修飾子 - public private(class,struct) [#f2079e32] - protectedは無い。 - デフォルトはpublic - コロンを使うC++スタイル、メンバ変数・関数に直接記述するJAVAスタイルの両方に対応 #code(c,){{ class A { //--- 公開修飾子(デフォルトpublic) // C++/Dスタイル public: void funcPubA(){} // public private: void funcPriA(){} // private // JAVA/C#/Dスタイル public void funcPubB(){} // public private void funcPriB(){} // private }; }} * オーバーライドチェック - override(class) [#a382e838] - D,C#と同じ * 不変条件 - invariant(class,pod,struct) [#h6f6ff79] - (all)Dのinvariantとほぼ同じ -- 呼び出されるタイミング --- publicなメンバ関数の実行直前・直後 --- publicメンバ変数にアクセスする直前・直後 --- コンストラクタの直後 --- デストラクタの直前 -- invariant関数内でpure constメンバ関数以外のメンバ関数を呼び出すことを禁止。 - <要検討>structで再帰呼び出しされたらどうしよう(classはカウンタ持たせればいいかな) -- ↑これってどういう意味だっけ; * 委譲 (class) [#ga454cd5] - interfaceのデフォルト実装を別オブジェクトに委譲する #code(c,){{ interface IButtonListener { abstract void onPushed(); void onFocused(){} }; class Hoge : IButtonListener { public: override void onPushed(){} }; class A : IButtonListener = mHoge { // IButtonListenerの関数を全てmHogeに委譲される // implementを使うと自動で次のように展開される // override void onPushed(){ mHoge.onPushed(); } // override void onFocused(){ mHoge.onFocused(); } private: Hoge@ mHoge; }; class B : public IButtonListener = mHoge { // onFocusedの関数だけ実装、その他はmHogeにまかせる override void onFocused() { /* */ } private: Hoge@ mHoge; }; }} * コンストラクタ - this() (class,pod,struct) [#ta13d165] - (all)D言語の形式を採用し、関数名はthisを使う - (all)別コンストラクタ関数コールは可能 - (all)どのコンストラクタよりも前に.Initデータをメモリ領域にセットされる(D言語と同じふるまいをする) - (pod)デフォルトコンストラクタは定義できない(0初期化固定) - (struct,pod)デフォルトコンストラクタは定義できない(0初期化固定) #code(c,){{ class A { public: this() { mY = mX + 1; } this(in int x, in int y) : this() { mX = x; mY = y; } int mX = 1; // 直接初期化子を書くことが出来る。ただし,コンパイル時に決まる定数しか書けない。 int mX = 1; // 直接初期化子を書くことが出来る。ただし,コンパイル・リンク時に決まる定数しか書けない。 int mY; // 指定がないとデフォルトコンストラクタが呼ばれる。 }; }} * デストラクタ - ~this() (class,struct) [#p2eecfc4] - D言語スタイルを採用 #code(){{ class A { public: ~this() { } }; }} * 静的コンストラクタ - static this() (class,struct,pod,utility) [#o27052fb] - D言語と同じ - 静的コンストラクタが呼ばれる前に,.initデータがメモリ領域にコピーされる。 #code(){{ class A { static int hoge = 1; static int foo; // hoge * 2を代入したいが,他の変数を参照することができない static this() { // この時点で,.initデータがコピー済み。 // つまり,hogeには1,fooには0(デフォルト値)が代入済み foo = hoge * 2; // ここなら他の変数を参照することができる。 } }; }} * 静的デストラクタ - static ~this() (class,struct,pod,utility) [#cd758315] - D言語と同じ #code(){{ class A { static ~this() { } }; }} * 静的メンバ関数 (class,interface,pod,struct,utility) [#ta1939b9] - D言語と同じ。 * 静的メンバ変数 (class,pod,struct) [#u1b23ba6] - D言語と同じ。 * メンバ関数 (class,interface,struct,pod) [#l90075b8] - (all)C++でいうメンバ関数のconst修飾子はあり。引数リストの括弧の後ろにconstを付ける。 - (class)抽象関数にoverrideキーワードが使える - (interface)純粋仮装関数には先頭にabstractキーワードを付ける - (interface)デフォルト実装はstatic関数として同じ名前の関数が定義される。 - (class)抽象関数にoverrideキーワードが使え,ちゃんと継承できていなければコンパイルエラーになる。 #code(c,){{ interface IName { string getName(){ return "NoName"; } // こう書くと自動でstatic関数が作られる // static string getName() { return "NoName"; } // IName.DEFAULT.getName( IName )でアクセスできる }; }} * メンバ変数 (class,struct,pod) [#xe0c9c25] - publicなメンバ変数は関数に展開される。 - こうすることで変数のオフセット情報を知る必要がなくなり,再コンパイルの回数を減らすことができる。 #code(c,){{ struct Hoge { public int a; // これは下記のように展開される // public ref int __mv_ref_a() // { // return a; // } // public const ref int __mv_ref_a()const // { // return a; // } static void test() { Hoge h; h.a = 3; // h.__mv_ref_a() = 3; に展開される h.a = Hoge().a + Hoge().a; // 展開後 // { // Hoge __tv00; // Hoge __tv01; // h.__mv_ref_a() = __tv00.__mv_ref_a() + __tv01.__mv_ref_a(); // } h.a += 3; // 展開後 // h.__mv_ref_a() += 3; } } }} ** inlineメンバ変数 [#rb185fd4] #code(c,){{ class Hoge { public inline Foo@ a; // こうするとメンバ変数にダイレクトにアクセスするようになる。 // invariantメソッドが実装されていても呼ばれなくなる。 // Fooのメンバ変数の構成が変更されると再コンパイルが必要になる。 }; }} |