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

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

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

固定ページ 2 / 2

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

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

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


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

> VC2005(VC8)でもコンパイル、リンクできるね。
>
> 紛らわしくするためにクラスと関係ないものを用意しても
>
> ON_BN_CLICKED(IDC_BUTTON1, &CMyDlg::OnBnClickedButton1)
> ON_BN_CLICKED(IDC_BUTTON1, &OnBnClickedButton1)
> ON_BN_CLICKED(IDC_BUTTON1, OnBnClickedButton1)

そうなんですよ、VC6でも、どの方法でも参照できてしまうんです
C++の仕様と外れている気がします
グローバルに OnBnClickedButton1 という関数があった場合どうなるのかと、
::がないから、自動で判断してくれるのかな

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

そうでしたね・・・ 関数の実体は一つでした

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

そうなんですけど
ただ、OnBnClickedButton1 ではメンバ関数へのポインタを表していないですよね

僕のC++の理解がいまいちかな?
どうなんでしょうか


返信引用
tetrapod
 tetrapod
(@tetrapod)
ゲスト
結合: 21年前
投稿: 830
 

歴史的順序を言えば
VC++6 の発売 → ISO/IEC 14882:1998 の採択 → ISO/IEC 14882:2003 に改定
の順番なので VC++6 は「現在国際標準となっている C++ 」には準拠してない。
一部合致、一部非合致なので混乱を招く動作をおこなっているようだ

1.VC++ 6 は以下の条項に非合致で & なしでもメンバへのポインタを生成する
ISO/IEC 14882:1998 5.3.1 単項演算子 3
< メンバへのポインタが形成されるのは、明示的に & を使用し、
< その演算対象を括弧なしの「修飾つき識別子」にしたときだけとする。

2.VC++ 6 は以下の条項に合致
ISO/IEC 14882:1998 8.5 初期化子 10
< 静的メンバに対する初期化子は、そのメンバのクラスの有効範囲内にある
規格書の例を引用
int a;
struct X {
static int a;
static int b;
};
int X::a=1;
int X::b=a; // この a は X::a

ということでメッセージマップマクロの展開結果であるところの
const AFX_MSGMAP_ENTRY C**Dlg::_messageEntries[] = {
{ ... (AFX_PMSG)&OnMyButton },
};
を VC++6 がどう解釈しているかを考えるに
2.より _messageEntries[] の初期化子 { } 内部は C**Dlg クラス内にあると判断
したがって非メンバな OnMyButton は、あっても無視される
1.より OnMyButton が修飾つきでないにもかかわらずメンバへのポインタを生成
しているだけだと思われる

VC++6 みたいな太古の遺物は窓から投げ捨てろ AA r


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

> 2.より _messageEntries[] の初期化子 { } 内部は C**Dlg クラス内にあると判断
> したがって非メンバな OnMyButton は、あっても無視される
> 1.より OnMyButton が修飾つきでないにもかかわらずメンバへのポインタを生成
> しているだけだと思われる

ということは、特殊な環境であって通常不可能ということですね

実は組み込みで日立のマイコンに MFC 的なクラスを作成しています
それをサブクラス化して、オーバライドすれば、CPU の機能
(A/D変換、D/A変換、パルス出力、ROM/RAMアクセス、I/O、割り込み、シリアル通信等)
を使えるようにしています

ただ、&Cxxx::func の書き方より、func だけで書けるほうが
かっこいいかなというところが始まりでした

コンパイラの具合なのか、ソースでなんとかなるのか
何か隠されたすべが MFC にはあるのではという期待でした。

ただ
> VC2005(VC8)でもコンパイル、リンクできるね。
>
> 紛らわしくするためにクラスと関係ないものを用意しても
>
> ON_BN_CLICKED(IDC_BUTTON1, &CMyDlg::OnBnClickedButton1)
> ON_BN_CLICKED(IDC_BUTTON1, &OnBnClickedButton1)
> ON_BN_CLICKED(IDC_BUTTON1, OnBnClickedButton1)

ともあります・・・

> VC++6 みたいな太古の遺物は窓から投げ捨てろ AA r

VC2005(VC8)でできなくなってれば考えたんですけど・・・


返信引用
tetrapod
 tetrapod
(@tetrapod)
ゲスト
結合: 21年前
投稿: 830
 

> &Cxxx::func の書き方より、func だけで書けるほうがかっこいいかな
俺的かっこいい基準より標準を優先させるほうがいいと思うが

> 何か隠されたすべが MFC にはあるのでは
隠された、とは言わない(きっちり文書化されているので)
VS2005+MFC の場合、下位(VC++6/MFC4.2)互換のための機能が準備されてるよ。
調査不足だな

_ATL_ENABLE_PTM_WARNING が定義されていないとき下位互換優先 (標準非合致)
古い VC++6/MFC4.2 の頃のコードが無警告でコンパイル通るようになっている
メッセージマップ中の ON_**(IDC_MYBUTTON, OnBnClickedMyButton) を認める

_ATL_ENABLE_PTM_WARNING が定義されているとき標準優先
メッセージマップ中でも &C**Dlg::OnBnClickedMyButton でなきゃダメ

ちなみに以下のコードをルネサス SH コンパイラはコンパイル通してしまった
# 下位互換優先ということか?ダメぢゃん
void func(int) { }
struct foo { virtual void func(int); };
struct bar : foo { static void (foo::*const table[])(int); };
void (foo::*const bar::table[])(int) = { func };
void foo::func(int) { void (foo::*p)(int)=func; }
動作は多分皆の期待通り p も table も foo::func を指し vtbl を介する


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

> _ATL_ENABLE_PTM_WARNING が定義されていないとき下位互換優先 (標準非合致)
> 古い VC++6/MFC4.2 の頃のコードが無警告でコンパイル通るようになっている
> メッセージマップ中の ON_**(IDC_MYBUTTON, OnBnClickedMyButton) を認める
> _ATL_ENABLE_PTM_WARNING が定義されているとき標準優先
> メッセージマップ中でも &C**Dlg::OnBnClickedMyButton でなきゃダメ

なるほど、勉強になります

> ちなみに以下のコードをルネサス SH コンパイラはコンパイル通してしまった
> # 下位互換優先ということか?ダメぢゃん
> void func(int) { }
> struct foo { virtual void func(int); };
> struct bar : foo { static void (foo::*const table[])(int); };
> void (foo::*const bar::table[])(int) = { func };
> void foo::func(int) { void (foo::*p)(int)=func; }
> 動作は多分皆の期待通り p も table も foo::func を指し vtbl を介する

は、こちらの環境では通りませんでした・・・
コンパイラのオプションかな

ん、ということは
_ATL_ENABLE_PTM_WARNING チックな物が存在している可能性があるのかな

>> &Cxxx::func の書き方より、func だけで書けるほうがかっこいいかな
>俺的かっこいい基準より標準を優先させるほうがいいと思うが

その通りですね


返信引用
tetrapod
 tetrapod
(@tetrapod)
ゲスト
結合: 21年前
投稿: 830
 

void foo::func(int n) {
void (foo::*p)(int)=&foo::func;
if (n>0) (this->*p)(n-1);
}
先の例を厳密規格合致+検証コード追加に書き換えてみたりする。これなら
俺の手元にあるところのコンパイラ複数種ですべて期待通りの結果になる。
期待通り= foo::func を vtbl 経由する仮想関数呼び出しとして展開
SH C/C++ Compiler 9.01.00.001
VC++6 SP6 (cl.exe 12.00.8804)
VS2005 with Vista update (cl.exe 14.00.50727.762)
gcc i686-pc-cygwin-gcc-3.4.4, hppa2.0w-hp-hpux11.00-3.3.4

> _ATL_ENABLE_PTM_WARNING チックな物が存在している可能性があるのかな
俺が/かーず氏が 誤読してるとアレげなので追加しとこう。
俺の手元にある SHC 9.01.00.001 は規格書厳密一致よりも下位互換を優先し
先の 5.3.1-3 はハナから無視してるだけだと思う。
俺の「ダメぢゃん」発言は &foo::func と書かなくてもコンパイル通る
すなわち 5.3.1-3 を無視してる点がダメという意図だったわけだが。

かーず氏の手元にある SHC はバージョンいくつだろうか?


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

> かーず氏の手元にある SHC はバージョンいくつだろうか?

SHC というか kpitだったりします
v0601 COFFです。

kpit 自体微妙ですが・・・
ルネサス関係ある会社でインドにあるみたいです


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

返信する

投稿者名

投稿者メールアドレス

タイトル *

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