■
id:banderさんところで知って面白そうなので実験してみた。
baseを超えてアクセスできるともっと便利なんだけどなぁ。
むりやりキャストしたら関係ないクラスの関数でもいけそうです。
すげーーーーー!マジこれは革命ですよ。
staticメンバ関数にして内部でわざわざポインタ受け取ってアロー演算子を使ってメンバにアクセスするのはもう古い!はず!
無名unionを使って普通の関数も登録できるようにした。
で、ここで気が付いたのだが、登録したthisポインタとクラス関数の型に関連が無いと、
Callbackを呼んでいるところでコンパイルエラーになることが判明。
なのでfuncbaseで適当にクラス関数型を作ってもしてもだめだった。。
でも一応普通の関数も呼べるしまぁいいかな。全員base派生しとけっていう話です。
もしかしたら無理やりキャストにより呼び出すことはできるかも。
と思って試したら出来た。
- BCB
BCBだと駄目だ!メンバ関数のアドレスをキャストできねぇ!
使えねぇ〜。
諦めてboost::bindとboost::functionを使ったほうがよさそうかな。
#include "stdafx.h"
#include
#include
#include
using namespace std;class base
{
public:
base(){;}
virtual ~base(){;}
};class funcbase
{
public:
funcbase(){;}
virtual ~funcbase(){;}
};class A : public base
{
private:
int a;
public:
A() { a = 0; }
A(int i) { a = i; }
virtual ~A() { a = 0; }
public:
void funcA(void) { cout << "funcA! = " << a << endl; }
};class B : public base
{
private:
int b;
public:
B() { b = 10; }
B(int i) { b = i; }
virtual ~B() { b = 0; }
public:
void funcB(void) { cout << "funcB! = " << b << endl; }
};typedef void (*FUNCTION)(void);
typedef void (funcbase::*CLASS_FUNCTION)(void);class CallbackHolder
{
private:
base *ptr;union
{
void *address;
CLASS_FUNCTION cfn;
FUNCTION fn;
};public:
CallbackHolder()
{
ptr = NULL;
address = NULL;
}CallbackHolder(base *p, CLASS_FUNCTION f )
{
Set(p,f);
}CallbackHolder( FUNCTION f )
{
Set(f);
}~CallbackHolder(){}
CallbackHolder &Set( base *p, CLASS_FUNCTION f )
{
ptr = p;
cfn = f;
return (*this);
}CallbackHolder &Set( FUNCTION f )
{
ptr = NULL;
fn = f;
return (*this);
}
void Callback(void)
{
if ( address == NULL ) return;if ( ptr )
(((funcbase *)ptr)->*cfn)();
else
fn();
}
};typedef vector
CallbackArray;
typedef vectorBaseArray; void test(void)
{
cout << "test" << endl;
}int main(int argc, char* argv[])
{
CallbackHolder cb;
CallbackArray cbs;
BaseArray bases;bases.push_back(new A());
bases.push_back(new A());
bases.push_back(new B());
bases.push_back(new B());// クラスのメンバ関数を登録.
cbs.push_back( cb.Set( bases[0], (CLASS_FUNCTION)A::funcA ) );
cbs.push_back( cb.Set( bases[1], (CLASS_FUNCTION)A::funcA ) );
cbs.push_back( cb.Set( bases[2], (CLASS_FUNCTION)B::funcB ) );
cbs.push_back( cb.Set( bases[3], (CLASS_FUNCTION)B::funcB ) );
// 普通の関数も登録.
cbs.push_back( cb.Set( test ) );// コールバック呼び出す.
for ( int i = 0 ; i < cbs.size() ; i++ )
{
cbs[i].Callback();
}for ( i = 0 ; i < bases.size() ; i++ )
{
delete bases[i];
}bases.clear();
getch();
return 0;
}
コールバックできた!
funcA! = 0
funcA! = 0
funcB! = 10
funcB! = 10
test