C++/CLI 研究
書誌
| tag | C++ |
| text | 唯野 |
| author | 渡邊誠人 |
| publisher | ソフトバンク |
| year | 『C MAGAZINE 2005.4』p.46-54 |
履歴
| 2005.12.24 | 読了 |
| 2005.12.28 | 公開 |
| 2007.2.9 | 修正 |
感想
C++/CLI は VC2003 でのマネージ拡張を更に推し進めたものである。そのため .net Framework プログラミングにおける C++ 言語拡張といってしまえばそれまでとなるが、C++/CLI では C# と並び標準化をも意識している──正しくはマネージ拡張の標準化作業版が C++/CLI なのだということである。C++ の拡張性を維持したまま Java などの便利な点を取り込んだといってしまっては乱暴か。しかし、GC、interface、Generic (= template)、finally キーワードなどは Java と同様である。これ以外では列挙型クラス/構造体、イベントハンドラ/オーバーライド専用を含む新しいキーワード(予約語)などが含まれている。
かくいう私もマネージ拡張や C# は MS だけのプロプライエタリな技術としか思っていなかった。しかし、C++/CLI は現状の肥大化した C++ に対する目指すべきひとつの方向性だと思う。コンピュータの歴史においては、基本的に複雑化しすぎたもの(学習曲線のきつくなり過ぎたもの)は延命できないという定理(というのはいいすぎかもしれないが)がある。プログラミング言語として最もつぶしの効くのが C++ だと信じる私としては、この動きは素直に歓迎したいと思う。
ちなみに VS2005 Express Editon が無償で DL 可能になっているが、以下の内容を実際に走らせてまではいない。私が基本的に VC よりも BCB 使いということもあるが、MFC/ATL を含まないため別途 Platform SDK が必要であるなど、手順が面倒そうなためである。
2007.2.9 補足
念のため補足しておくと C++/CLI は、あくまでも .net Framework に対する C++ 用インタフェースであるため、あくまでも実行は CLR を介して行われる。そのためパフォーマンスは期待できない。
抄録
47-48
ref 修飾子を付与してクラスや構造体を宣言するとガベージコレクション(GC)の対象となる。GC の対象となったオブジェクトは明示的な delete が不要で、new の代わりに gcnew を使う。ガベージコレクションはオブジェクトがスコープを抜けた時点で行われ、もちろんデストラクタも呼び出される。また、GC 使用を明示するために handle 型であることを示す ^ (ハット)をポインタ型の * (アスタリスク)のように使用する。逆に値を直接含むリファレンスでない型(GC の不要な型)であることを明示したい場合は value を付与する。
// ref
ref class X // GC 対象クラス
{
public:
int i;
int getX(){return i;}
};
int main()
{
X^ px; // handle型
px = gcnew X; // インスタンスの生成
px->i = 100;
int x = px->getX();
}
// value
#include "stdafx.h"
using namespace System;
value struct V // GC 不要の型
{
int i;
}
int _tmain()
{
V v1, v2;
v1.i = 1;
v2 = v1;
v2.i = 2;
return 0;
}
48
interface 修飾子によってインタフェースを独立させ、定義と実装を分離することができる。Java の interface と同じ。
public interface class A
{
void f(Object o); // 宣言のみで実装は行えない
}
48-49
列挙型をクラス/構造体として宣言できる。体裁はクラスだが内容を列挙型の値(int)として参照できる。何でもクラスにしておきたい人向けか ?
enum class Days{ SUN=1, MON, TUE, WED, THU, FRI, SAT};
int _tmain()
{
int x = (int)Days::SUN; // 1 が入る
}
49-50
イベントドリブンを実装するために、プロパティ宣言のための property、メソッド宣言のための delegate、イベントハンドラ宣言のための event 修飾子が追加されている。要は property は JavaBeans、delegate は委譲メソッド、event はコールバックのそれぞれを仕様として含んだということ。
// property
public ref class C
{
private:
int i;
public:
property String^ sp; // プロパティ
property int ip // get/set メソッド
{
int get();
void set(int v)
{
i = v;
}
}
};
int C::Property_Block::get() // get() 実装
{
return i;
}
int main()
{
C^ c = gcnew C;
c->sp = "test";
c->ip = 100;
}
// delegate
public delegate void F(int i); // 委譲先
ref class A // 委譲元(委譲元と委譲先の引数は同じ)
{
public:
void f1(int i)
{
Console::WriteLine("f1", i);
}
void f2(int i)
{
Console::WriteLine("f2", i);
}
static void f3(int i) // 静的メソッド
{
Console::WriteLine("f3", i);
}
};
int main()
{
A^ a = gcnew A;
F^ f; // (このとき f == NULL は保障されるのか ? : 唯野注)
if(f) // 未割り当てなので偽
{
f(7);
}
f = gcnew F(a, &A::f1); // A::f1() を F として登録
if(f)
{
f(8);
}
f += gcnew F(a, &A::f2); // 追加登録
f(9); // f1() と f2() の双方が呼び出される
f -= gcnew F(a, &A::f1); // A::f1() の解除
f->Invoke(10); // 登録と同時に呼び出す場合
F^ static_f = gcnew F(&A::f3); // 静的メソッドを登録
static_f(11); // 静的メソッドの呼び出し
}
// event
using namespace System; // CLR を使う
delegate void ClickEventHandler(int, double);
delegate void DbClickEventHandler(String^);
ref class EventDef // イベント定義クラス
{
public:
// イベントハンドラの宣言
event ClickEventHandler^ OnClick; // クリック
event DbClickEventHandler^ OnDbClick; // ダブルクリック
void PseudoEvents()
{
OnClick(100, 1.2345);
OnDbClick("Hello");
}
};
ref class EventRcv // イベント受信クラス
{
public:
void OnMyClick(int i, double d)
{
Console::WriteLine("OnClick: {0}, {1}", i, d);
}
void OnMyDbClick(String^ s)
{
Console::WriteLine("OnDbClick: {0}", s);
}
};
int main()
{
EventDef^ evtDef = gcnew EventDef();
EventRcv^ evtRcv = gcnew EventRcv();
// イベントの登録(複数可能)
evtDef->OnClick +=
gcnew ClickEventHandler(evtRcv, &EventRcv::OnClick);
evtDef->OnDbClick +=
gcnew DbClickEventHandler(evtRcv, &EventRcv::OnDbClick);
EvnetDef->PseudoEvents(); // イベントの擬似発生
// イベントの解除
evtDef->OnClick -=
gcnew ClickEventHandler(evtRcv, &EventRcv::OnClick);
evtDef->OnDbClick -=
gcnew DbClickEventHandler(evtRcv, &EventRcv::OnDbClick);
}
全文を読まれる場合はログインしてください
