- 締切済み
静的でないメンバ関数の呼び出しが正しくありません
コンパイル時に「静的でないメンバ関数の呼び出しが正しくありません」となってしまいます。 普通の関数からメンバー関数を呼び出すには、どう記述すればいいのでしょうか? void MyDataHandler(sFrameOfData* FrameOfData) { CFrrjiftestDlg::sndrobot(); ← ここがコンパイルエラー } void CFrrjiftestDlg::sndrobot() { いろいろ記述 } //*** 以下、ヘッダー class CFrrjiftestDlg : public CDialog { DECLARE_DYNAMIC(CFrrjiftestDlg); friend class CFrrjiftestDlgAutoProxy; // Construction public: CFrrjiftestDlg(CWnd* pParent = NULL); // standard constructor virtual ~CFrrjiftestDlg(); void msubInit(); void sndrobot(); ←ここで宣言 };
- みんなの回答 (9)
- 専門家の回答
みんなの回答
- wormhole
- ベストアンサー率28% (1626/5665)
余計なお世話かもしれませんが 回答者の方々が言わんとしてることをよく把握されるのがよろしいかと思います。 見た感じ「何をいってるかはわからないけど参考に修正してみた。(理解し修正してるわけではないので当然のごとく)コンパイルエラーになった。」の繰り返しです。 staticメンバ関数(変数)と非staticメンバ関数(変数)の違いはわかっていらっしゃいますか?
- 麻野 なぎ(@AsanoNagi)
- ベストアンサー率45% (763/1670)
> それで早速試してみたのですが、msubInit() の中で使用している CFrrjiftestDlgのメンバー関数で定義しているものすべてが、 > ~への参照が正しくありません。 > 左側がクラス、構造体、共用体、ジェネリック型へのポインタではありません それは、msubInit() が、関数の中で、非 static なメンバを直接参照しているということです。 言い換えれば msubInit() は、非 static でなければならないということです。 もともと 非 static なものを static で宣言すると、つじつまが合わないことになります。 さらに言い換えると、実は、msuInit() で初期化する限り、 > pNumReg8 はアプリケーションで一つで使い回しするものです。 であることはできないということです。 pNumReg8 「だけ」をstatic にして、これを初期化する static な関数を定義して、アプリケーションの冒頭でそれを呼び出すとか、きれいではないですが、 class CFrrjiftestDlg : public CDialog { public: static _DataNumReg *pNumReg8; } として、アプリケーションの冒頭で、(msubInit とかではなくて) CFrrjiftestDlg::pNumReg8 = new _DataNumReg(pDataTable->AddNumReg(NUMREG_INT, 21, 21)); で単独で初期化するのが正しいのではないかな?
- a_kwn
- ベストアンサー率34% (8/23)
1つの CFrrjiftestDlg インスタンスしかこのコールバックを利用しないんだったら、 ”クラスに静的な CFrrjiftestDlg* 変数でも作って、そこに this ポインタを入れて置く” ってのは、よくつかわれる逃げ手だと思います。 決して推奨はできませんが・・・。
- hidebun
- ベストアンサー率50% (92/181)
これって、何のライブラリを使っているの? その辺り、全く情報がないけれど、Googleで検索したら、以下のページにたどり着きました。 これですか? http://code.google.com/p/alufr-ros-pkg/source/browse/trunk/cortex_stream/src/cortex_stream.cpp?spec=svn1665&r=1665 もし、仮にこのライブラリを使っているとすると、このサンプルを見ると、 // Corext Data Handler is called everytime new data is recieved from the cortex thread // this has to be global, so we call the actual handler (member function) in here void CortexDataHandler(sFrameOfData* frame, void *params) { ((MocapInterface*)params)->handleCortexFrame(frame); } ってことで、Data Handlerの関数は、結構な頻度で呼ばれたりするのではないのでしょうか。 そのたびに、ダイアログを一時的に生成するというのは、なんとなく変な気がするけど、 その辺りはどんなもんなんでしょうか? それから、このサンプルでは、ハンドラ登録関数でthisを渡して、ハンドラの第二引数paramで受け取り、 それをキャストして使ってるみたいなんだけど、 // start data handling Cortex_SetDataHandlerFunc(CortexDataHandler, this); こういう機構がきちんと使えてないだけなんじゃないかと思うんだけど、どうかな?
- 麻野 なぎ(@AsanoNagi)
- ベストアンサー率45% (763/1670)
結論から言えば、全体の設計が大きく間違っていなければ、No.1 の補足をちょっと変更して、 void MyDataHandler(sFrameOfData* FrameOfData) { CFrrjiftestDlg obj; obj.msubInit(); obj.sndrobot(); } でOKじゃないのかな? まず、static をつけていないメンバ関数を直接呼び出す方法はありません。 非 static なメンバ関数は、オブジェクト指向の立場からいえば、呼び出すものではなく、そのクラスのインスタンスへのメッセージです。 そういうわけで、「そのクラスのインスタンス」がない限り呼び出すことはできません。 逆に言えば、クラスの概念がわかっていれば、非 static なメンバ関数を直接呼ぶ必要も無いことがわかるということになっています。 たとえば、 class CFrrjiftestDlg : public CDialog { _DataNumReg *pNumReg8; } と書かれたときの、*pNumReg8; という変数は誰のものなのか? という理解が必要です。 この変数は(static じゃないので)CFrrjiftestDlg のインスタンスが個々に持ちます。 つまり、 void MyDataHandler(sFrameOfData* FrameOfData) { CFrrjiftestDlg obj; ← (2) obj.sndrobot(); } という流れだと、obj が生成されて、この obj のために、pNumReg8 がひとつ作られます。 ここで作られたものは、(必要なら)ここで初期化する必要があります。 直接呼ぶのではなく、obj へのメッセージとして呼ぶ必要があります。 また、もしも、pNumReg8 というのが本質的に一つしか無くて、アプリケーションの最初で一回初期化すべき (MyDataHandler の呼び出し時に毎回初期化すべきでないとき)であれば、それは、クラス全体でひとつのものなので、static メンバになります。 その場合は、ヘッダファイルの記述で、 staic _DataNumReg *pNumReg8; static void msubInit(); void sndrobot(); とします。(クラス全体でひとつのものは、static) 呼び出しは、アプリケーションの最初に(この場合だと、MyDataHandler の中ではなくて、本当に一回しか動かないところ) CFrrjiftestDlg::msubInit(); をおいておきます。
補足
pNumReg8 はアプリケーションで一つで使い回しするものです。 それで早速試してみたのですが、msubInit() の中で使用している CFrrjiftestDlgのメンバー関数で定義しているものすべてが、 ~への参照が正しくありません。 左側がクラス、構造体、共用体、ジェネリック型へのポインタではありません などのコンパイルエラーになってしまいました。 修正したのは、 ヘッダーファイルの static _DataNumReg *pNumReg8; //← staticに変更 static void msubInit(); //← staticに変更 CFrrjiftestDlg::OnInitDialog() //の中の CFrrjittestDlg::msubInit(); //←CFrrjittestDlg::を追加 void MyDataHandler(sFrameOfData* FrameOfData) { //CFrrjiftestDlg obj; //← これはコメントアウトにして、 //obj.sndrobot(); //←これはコメントアウトにして、 CFrrjiftestDlg::sndrobot(); //←この書き方に変更 以上を変更して、コンパイルしたら冒頭のエラーとなりました。
- Tacosan
- ベストアンサー率23% (3656/15482)
そこのコード片のどこで CFrrjiftestDlg::msubInit を呼び出しているんですか?
補足
msubInit は、OninitDialog の中で呼んでいます。
- Tacosan
- ベストアンサー率23% (3656/15482)
#1 への補足を見たが.... とりあえず落ち着け. 「(1)で、new したものが、(2)でクリアされてしまうので、(3)で使えない。」と書いているが, それはどう確認したの? そのプログラム片を見る限り, そもそも「(1) で new」などしていないようにしか読めないぞ.
補足
pNumReg8 = new _DataNumReg(pDataTable->AddNumReg(NUMREG_INT, 21, 21)); ← (1) まず、ここで、pNumReg8 を初期化。AddNumRegに値をセットしている。 実行時に、pNumReg8の値を参照したら、正しく初期化されていた。 MyDataHandlerの関数内で、(2)の処理を通過した以後に、pNumReg8を参照したら、(1)の初期化した値が全部クリアされていた。 CFrrjiftestDlg obj; ← (2) これをやっているので、CFrrjiftestDlg がクリアされるのは当然? やりたいことは、 (1)で、AddNumRegに値をセットしているが、この状態で、(3)の処理をしたい。 現状では、(1)pNumReg8でセットしたAddNumRegの値がクリアされているので、プログラムが異常終了してしまう。 こんな説明でわかりますか?
- wormhole
- ベストアンサー率28% (1626/5665)
CFrrjiftestDlg::OnBnClickedButton1()での this をどうにかしてMyDataHandler()に教えてあげてください。
補足
その方法が分かればいいのですが、どう書いていいのやら。。。。
- hitomura
- ベストアンサー率48% (325/664)
void MyDataHandler(sFrameOfData* FrameOfData) { CFrrjiftestDlg dlg; dlg.sndrobot(); } CFrrjiftestDlg::sndrobot(); という呼び出し方をどうしてもしたければ、 class CFrrjiftestDlg : public CDialog { /* 中略 */ static void sndrobot(); }; とします。ただし、この場合静的でない(staticを付けずに宣言した)メンバ関数・メンバ変数は使用できません。
補足
教えていただいた方法で、コンパイルエラーはなくなりましたが、ちょっと問題が。。。 class CFrrjiftestDlg : public CDialog { _DataNumReg *pNumReg8; } void CFrrjiftestDlg::msubInit() { pNumReg8 = new _DataNumReg(pDataTable->AddNumReg(NUMREG_INT, 21, 21)); ← (1) } void MyDataHandler(sFrameOfData* FrameOfData) { CFrrjiftestDlg obj; ← (2) obj.sndrobot(); } void CFrrjiftestDlg::sndrobot() { if(pNumReg8->SetValuesInt(regi,se_val,kosu)) ← (3) } void CFrrjiftestDlg::OnBnClickedButton1() { Cortex_SetDataHandlerFunc(MyDataHandler); ← (4) } (1)で、new したものが、(2)でクリアされてしまうので、(3)で使えない。 目的は、(1)でnewしたものが、(3)でそのまま使えるようにしたい。 (4)セットされた関数は、相手から通信を待ち続けるので、常時、MyDataHandler が呼ばれ続けます。そのため、MyDataHandler 内や、sndrobot 内で、pNumReg8 = new _DataNumReg(pDataTable->AddNumReg(NUMREG_INT, 21, 21)); をすると実行時にエラーとなってしまいます。 どうすれば、(1)でnewしたものが、そのまま(3)で使用できるようになるのでしょうか?
補足
見つけて頂いたものと同じメーカーのものなのですが、ちょっと定義が違っていて、 提供されているヘッダに、 DLL int Cortex_SetDataHandlerFunc(void (*MyFunction)(sFrameOfData* pFrameodData)); が、書かれています。 なので、 Coretex_SetSataHandlerFunc(MyDataHandler,this); と書くと、”関数に2個の引数を指定できません”というコンパイルエラーとなります。 void CortexDataHandler(sFrameOfData* frame, void *params) って、修正しちゃっても大丈夫なのか、わかりません。。。 確かに、これであれば、 Cortex_SetDataHandlerFunc(CortexDataHandler, this); この方法でうまくいくような気がします。 それと、 ってことで、Data Handlerの関数は、結構な頻度で呼ばれたりするのではないのでしょうか。 そのたびに、ダイアログを一時的に生成するというのは、なんとなく変な気がするけど、 Data Handler関数は頻繁に呼ばれるので、ダイアログを一時的に生成するのは、おかしいです。メンバー関数をうまく引き渡しできず、苦肉の策で書いた次第です。 まだ、問題は解決できていません。