Home > .NET Framework Archive
.NET Framework Archive
仮想関数を generic にする
- 2009年6月 1日 13:35
- .NET Framework | C++/CLI
C++では、メンバ関数テンプレートを仮想関数にできない。ところが、C++/CLI ではテンプレートに良く似た機能である generic を仮想関数につけることができる。これにはどんなトリックが隠されているのだろう?
まずは、次のようなコードから。
public ref class Base // ref class なので参照型
{
public:
generic <typename T> // generic を仮想関数につける
virtual int Func(T in) { // T は任意の型
return sizeof(in); // T 型のサイズを返す(本当は size_t だけど)
}
};
public ref class Derived: public Base
{
public:
generic <typename T>
virtual int Func(T in) override { // Base::Func を override
return sizeof(in) * 2; // T 型のサイズを倍にして返す
}
};
これはTがどんな型であっても正しく動作する。Derived のインスタンスを Base のハンドルで参照しても、Derived 側の Func が呼ばれる。完璧だ。
C++ では、Tの型が決まらないと仮想関数テーブルを構築できず、Tの型を知るためには全ての翻訳単位を調べなければならない。よって、このようなメンバ関数は禁止されている。そして、以前のエントリでは「なんだ、その都度 JIT コンパイルすればいいじゃん」という結論で終わっていた。今回は、これをもう少し調べてみようと思う。
- Comments: 0
- TrackBack (Close): 0
コレクションの永続化
- 2009年4月 6日 22:16
- .NET Framework | C++/CLI
.NET Framework で独自のコントロールを作りたい場合は、UserControl から派生させたクラスを用意すればよい。一般的に、自作コントロールには独自のプロパティも含まれており、そのプロパティが自作クラスになっていることも多いはず。今回は、自作クラスの配列をプロパティとして持たせたところ大ハマリしたという話。
ある自作コントロールに自作クラス MyItem の配列をプロパティとして持たせたいと思い、System::Collections::Generic::List<MyItem^>^ 型のプロパティ MyItemList を追加することにした。cli::array ではなく List を使っているのは vector っぽく使いたいためだが、この違いは本質ではない(と思う)。悲劇の始まりは次のようなコードからだ。
ref class MyItem;
ref class MyCtrl : public System::Windows::Forms::UserControl
{
// ... 色々あって、
private:
System::Collections::Generic::List<MyItem^>^ m_itemList; // リストの実体
public:
MyCtrl(void) {
InitializeComponent();
// コンストラクタで m_itemList を確保する
m_itemList = gcnew System::Collections::Generic::List<MyItem^>;
}
public:
property System::Collections::Generic::List<MyItem^>^ MyItemList { // このプロパティは
System::Collections::Generic::List<MyItem^>^ get() { // get だけしか持っていない(set は許可しない)
return m_itemList; // 中身は自由にしても構わないが、リストそのものはコチラで管理させてくれ
}
}
// ... 色々あるよね
};
- Comments: 0
- TrackBack (Close): 0
Home > .NET Framework Archive