MonaForms/delegate


MonaForms

MonaFormsのdelegateについて

コールバック

実例

#include <stdio.h>
void test() {
	printf("test\n");
}
int main() {
	void(*func)() = test;
	(*func)();
	return 0;
}

メンバ関数に対するコールバック

さて、C++。

何も考えずにクラス化

#include <stdio.h>
class Test {
public:
	void test() {
		printf("test\n");
	}
};
int main() {
	void(*func)() = Test::test;
	(*func)();
	return 0;
}

コンパイルしてみると・・・

$ g++ test.cpp
test.cpp: In function `int main()':
test.cpp:9: error: invalid use of non-static member function `void Test::test()'
test.cpp:9: error: invalid use of non-static member function

そうは問屋が卸さないという感じ。(泣

static

non-staticだと文句を付けられているので、staticに変更してみる。

#include <stdio.h>
class Test {
public:
	static void test() {
		printf("test\n");
	}
};
int main() {
	void(*func)() = Test::test;
	(*func)();
	return 0;
}

問題なく動く。

$ g++ test.cpp
$ ./test
test

インスタンス

だがしかし、staticだとインスタンスメンバにアクセスしたいときに困る。とりあえず引数として渡してみる。

#include <stdio.h>
class Test {
private:
	int no;
public:
	Test(int n) : no(n) {}
	static void test(Test* p) {
		printf("%d\n", p->no);
	}
};
int main() {
	Test a(1), b(2);
	void(*func)(Test*) = Test::test;
	(*func)(&a);
	(*func)(&b);
	return 0;
}

問題なく動く。

$ g++ test.cpp
$ ./test
1
2

正規の書式

実はインスタンスメンバにコールバックさせる正規の書式がある。

#include <stdio.h>
class Test {
private:
	int no;
public:
	Test(int n) : no(n) {}
	void test() {
		printf("%d\n", no);
	}
};
int main() {
	Test a(1), b(2);
	void(Test::*func)() = &Test::test;
	(a.*func)();
	(b.*func)();
	return 0;
}

型縛り

型が限定されるので、次の2つに互換性がない。

class Test1 {
public:
	void test() { printf("Test1\n"); }
};
class Test2 {
public:
	void test() { printf("Test2\n"); }
};

仮想関数

同一の関数ポインタで扱う場合、仮想関数を使うしかない。

#include <stdio.h>
class Test {
public:
	virtual void test() = 0;
};
class Test1 : public Test {
public:
	virtual void test() { printf("Test1\n"); }
};
class Test2 : public Test {
public:
	virtual void test() { printf("Test2\n"); }
};
int main() {
	Test *a = new Test1(), *b = new Test2();
	void(Test::*func)() = &Test::test;
	(a->*func)();
	(b->*func)();
	return 0;
}

実行結果

$ g++ test.cpp
$ ./test
Test1
Test2

テンプレート併用コールバック

#include <stdio.h>
class IDelegate {
public:
	 virtual void Invoke() = 0;
};
template <class T> class Delegate : public IDelegate {
private:
	T* target;
	void(T::*func)();
public:
	Delegate(T* t, void(T::*f)()) : target(t), func(f) {}
	virtual void Invoke() { (target->*func)(); }
};
class Test1 {
public:
	void foo() { printf("Test1\n"); }
};
class Test2 {
public:
	void bar() { printf("Test2\n"); }
};
int main() {
	Test1 a;
	Test2 b;
	IDelegate* aa = new Delegate<Test1>(&a, &Test1::foo);
	IDelegate* bb = new Delegate<Test2>(&b, &Test2::bar);
	aa->Invoke();
	bb->Invoke();
	return 0;
}

実行結果

$ g++ test.cpp
$ ./test
Test1
Test2

アンケート

この記事についてのご感想をお寄せください。

選択肢 投票
意味不明 1  
既に知ってる 5  
勉強になった 21  
多態でいいじゃん 0  
C言語でいいじゃん 0  
Javaでいいじゃん 1  
プログラミング自体やらない 0  

MENU

now: 1

リンク


最新の20件
2018-05-03 2017-09-29 2017-04-25 2017-01-10 2016-12-11 2016-10-04 2016-08-14 2016-06-05 2016-05-29 2016-04-15 2015-12-28 2013-02-25 2013-02-21 2013-02-20 2013-02-12 2013-02-11 2013-02-10
最新の20件
2010-02-01 2010-01-31 2010-01-30 2010-01-29 2010-01-16

Counter: 12016, today: 4, yesterday: 0

リロード   新規 編集 凍結 差分 添付 複製 改名   トップ 一覧 検索 最終更新 バックアップ   ヘルプ   最終更新のRSS

Last-modified: 2015-12-28 (月) 15:55:59 (881d);  Modified by mona
PukiWiki 1.4.6 Copyright © 2001-2005 PukiWiki Developers Team. License is GPL.
Based on "PukiWiki" 1.3 by yu-ji
Powered by PHP 5.2.17
HTML convert time to 0.036 sec.