メッセージマップに登録する関数ポインタについて – プログラミング – Home

メッセージマップに登録する関数ポインタ...
 
通知
すべてクリア

[解決済] メッセージマップに登録する関数ポインタについて

固定ページ 1 / 2

かーず
 かーず
(@かーず)
ゲスト
結合: 17年前
投稿: 10
Topic starter  

ポインタについての質問です

たとえばCxxxDlgというダイアログクラスで
hファイル内で
DECLARE_MESSAGE_MAP()
があって

cppファイル内で
BEGIN_MESSAGE_MAP(CxxxDlg, CDialog)
ON_BN_CLICKED(IDC_BUTTON1, OnBnClickedButton1)
END_MESSAGE_MAP()
とあるとしますが、

ここで OnBnClickedButton1 と記述してあるものは
関数ポインタの事を指すと思います

気になっているのは
ここの定義の部分はstaticで
このポインタはCxxxDlgクラスのメンバ関数ポインタで
&CxxxDlg::OnBnClickedButton1
としなければいけないような気がするのですが
何か秘密があるのでしょうか?

ご教授ください
よろしくお願いします


引用未解決
トピックタグ
επιστημη
 επιστημη
(@επιστημη)
ゲスト
結合: 22年前
投稿: 1301
 

マクロなんだから
ON_BN_CLICKED(IDC_BUTTON1, OnBnClickedButton1)
これがどう展開されるか確認してから質問するのがスジちゃいますか?


返信引用
かーず
 かーず
(@かーず)
ゲスト
結合: 17年前
投稿: 10
Topic starter  

ON_BN_CLICKEDは最終的には

#define ON_BN_CLICKED(id, memberFxn) \
ON_CONTROL(BN_CLICKED, id, memberFxn)

{ WM_COMMAND, (WORD)BN_CLICKED, (WORD)id, (WORD)id, AfxSigCmd_v, \
(static_cast< AFX_PMSG > (memberFxn)) },
と展開されていると思います

ただ、memberFxnには OnBnClickedButton1 と入っていまして
メンバ関数ポインタを指す形式の &CxxxDlg::OnBnClickedButton1 ではありません

static 部分ですからスコープは外れていて
これだと グローバルのOnBnClickedButton1() というものを
探しにいくと思うんですけど
探しにいかず ちゃんと CxxxDlg::OnBnClickedButton1() にたどり着きます

どこか見落としているマクロがあるんでしょうか?


返信引用
επιστημη
 επιστημη
(@επιστημη)
ゲスト
結合: 22年前
投稿: 1301
 

正直わかんないです。
VC++8では
ON_BN_CLICKED(IDC_BUTTON1, &XXX::OnBnClickedButton1)
となってますので。


返信引用
かーず
 かーず
(@かーず)
ゲスト
結合: 17年前
投稿: 10
Topic starter  

はい
ON_BN_CLICKED(IDC_BUTTON1, &XXX::OnBnClickedButton1)
という書き方であれば、疑問はどこにもなかったのですが

自分は VC++.net の環境ですが
ON_BN_CLICKED(IDC_BUTTON1, OnBnClickedButton1)
となります

どこかスコープを操作している部分があるのか、
いくら目にとまった、マクロ等を展開していっても
自分の能力の無さか、たどり着けませんでした

きっと何か隠れているような気がしてなりません


返信引用
RAPT
 RAPT
(@RAPT)
ゲスト
結合: 22年前
投稿: 310
 

# VCのバージョンは?
BEGIN_MESSAGE_MAP マクロの実装を調べてみてください。


返信引用
wclrp ( 'o')
 wclrp ( 'o')
(@wclrp ( 'o'))
ゲスト
結合: 18年前
投稿: 287
 

確かに昔はXXX::ついてなかったね。

以下はVC6で試した。
VC8はあるけどVC7.x系はインストールに失敗するので使ってない。

ここはメンバ関数へのポインタでありキャストしても
グローバル(メンバ関数じゃない)関数へのポインタを
メンバ関数へのポインタをキャストすることは
VC6でもreinterpret_castでもコンパイルエラーになるんじゃない。

上記でメンバ関数なら可能と判断した場合は
const HOGE XXX::data[] = { &メンバ関数 , ~ };
では、XXX::メンバ関数が候補になるようですね。

const HOGE XXX::data[] = { &YYY::メンバ関数 , ~ };
としたいならYYYは省略できない。

C++の規格としてはこういう規則なのか知りませんが。


返信引用
かーず
 かーず
(@かーず)
ゲスト
結合: 17年前
投稿: 10
Topic starter  

typedef void (AFX_MSG_CALL CCmdTarget::*AFX_PMSG)(void);
と宣言がありまして、このメンバ関数ポインタに代入するようです
メンバ関数ポインタですので、基本的には普通の関数ポインタは代入できないと思いま
す。
ただし、スコープ内にあれば、グローバルでなくても候補として XXX:: のメンバを探す
と思います。
ただ、この配列に代入するに当たって、この配列は static にて宣言されていて、
スコープは届かないと思うんです。
不思議です。namespace 的なものもマクロからは見つけられません。
特殊な仕様であって仕方ないと考えるしか、ないのでしょうか?
知らなくてもいい部分かも知れませんが、異常に気になって先に進めません・・・
A型です


返信引用
επιστημη
 επιστημη
(@επιστημη)
ゲスト
結合: 22年前
投稿: 1301
 

> ただ、この配列に代入するに当たって、この配列は static にて宣言されていて、
> スコープは届かないと思うんです。

なんで? その配列が XXX のメンバであるならXXXスコープにあるんちゃう?


返信引用
wclrp ( 'o')
 wclrp ( 'o')
(@wclrp ( 'o'))
ゲスト
結合: 18年前
投稿: 287
 

同じ名前があっても
コンパイラがあいまいと判断しなかったら
コンパイルエラーにならないからな。


返信引用
wclrp ( 'o')
 wclrp ( 'o')
(@wclrp ( 'o'))
ゲスト
結合: 18年前
投稿: 287
 

bar boo::foo[] = { &hoge };
の{}中はbooのスコープになるということなのかな。

でも検索したけどそれらしい説明に触れているところは見つからなかった。

boo::foo[1] = &hoge;
は、booのスコープにならなかった。

VC6の結果論ですけど。


返信引用
かーず
 かーず
(@かーず)
ゲスト
結合: 17年前
投稿: 10
Topic starter  

> なんで? その配列が XXX のメンバであるならXXXスコープにあるんちゃう?

その配列は static です。
static はある意味グローバルだと思うんですが、
そうでないものはインスタンスがない限り見えないというかアクセスできないと思いま

見えない this ポインタを存在させるために、メンバポインタやメンバ関数ポインタな
どの
形があると思っています
Cxxx::*yyy という形で Cxxx クラス内のメンバポインタを宣言し、
&Cxxx::zzz という形で ポインタを取得する
これはおそらく 内部的に this ポインタからのオフセット的な意味合いがあって、
どこにインスタンスが生成されても正しいインスタンスを見つける仕組みではないか
と・・・
では、static ではないメンバポインタへの参照を、普通の参照方法で
正しいインスタンス内のメンバをどうやって参照できるのか、できないと思います。

と思ってましたが、間違っていますでしょうか?


返信引用
επιστημη
 επιστημη
(@επιστημη)
ゲスト
結合: 22年前
投稿: 1301
 

えと、VC6でのお話ですよね。単にコンパイラの不備じゃないすか?

VC8だと
#include <iostream> // cout, endl

class foo {
public:
typedef void (foo::*func)();
void f() { std::cout << foo::f\n; }
void g() { std::cout << foo::g\n; }
static func table[2];
};

foo::func foo::table[] = {
&foo::f, // これならOK
g // error
};

int main() {
foo f;
(f.*foo::table[0])();
}


返信引用
かーず
 かーず
(@かーず)
ゲスト
結合: 17年前
投稿: 10
Topic starter  

でも、どう考えても C++ 的には間違いだと思います

おそらくどこかにクラスを偽装した namespace 的なものが存在し、
スコープを同一CPPファイル内まで拡張しているのかと考えていました

もしくは動的に生成されたクラス内の関数は普通ヒープに展開されていてると思います
で、static の部分は既にメモリ上にグローバルとして展開されていると思います
ですから、static 側からその他のメンバは参照できないと思います
そうすると static にしかけがあって、
実はグローバルを参照する変数に置き換えられているとか

いろいろ考えてはみましたが・・・

> えと、VC6でのお話ですよね。単にコンパイラの不備じゃないすか?

そういうことで納得しときます・・・


返信引用
wclrp ( 'o')
 wclrp ( 'o')
(@wclrp ( 'o'))
ゲスト
結合: 18年前
投稿: 287
 

VC2005(VC8)でもコンパイル、リンクできるね。

紛らわしくするためにクラスと関係ないものを用意しても

void OnBnClickedButton1()
{
}

以下のどの書き方でも

ON_BN_CLICKED(IDC_BUTTON1, &CMyDlg::OnBnClickedButton1)
ON_BN_CLICKED(IDC_BUTTON1, &OnBnClickedButton1)
ON_BN_CLICKED(IDC_BUTTON1, OnBnClickedButton1)

クラス内の関数は普通ヒープに展開されないよ。

staticメンバ関数からstaticではないメンバを参照できないけど
メンバ関数へのポインタは参照できるよ。


返信引用
固定ページ 1 / 2

返信する

投稿者名

投稿者メールアドレス

タイトル *

プレビュー 0リビジョン 保存しました
共有:
タイトルとURLをコピーしました