• 締切済み

静的でないメンバ関数の呼び出しが正しくありません

コンパイル時に「静的でないメンバ関数の呼び出しが正しくありません」となってしまいます。 普通の関数からメンバー関数を呼び出すには、どう記述すればいいのでしょうか? 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();   ←ここで宣言 };

みんなの回答

  • wormhole
  • ベストアンサー率28% (1621/5657)
回答No.9

余計なお世話かもしれませんが 回答者の方々が言わんとしてることをよく把握されるのがよろしいかと思います。 見た感じ「何をいってるかはわからないけど参考に修正してみた。(理解し修正してるわけではないので当然のごとく)コンパイルエラーになった。」の繰り返しです。 staticメンバ関数(変数)と非staticメンバ関数(変数)の違いはわかっていらっしゃいますか?

回答No.8

> それで早速試してみたのですが、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)
回答No.7

1つの CFrrjiftestDlg インスタンスしかこのコールバックを利用しないんだったら、 ”クラスに静的な CFrrjiftestDlg* 変数でも作って、そこに this ポインタを入れて置く” ってのは、よくつかわれる逃げ手だと思います。 決して推奨はできませんが・・・。

  • hidebun
  • ベストアンサー率50% (92/181)
回答No.6

これって、何のライブラリを使っているの? その辺り、全く情報がないけれど、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); こういう機構がきちんと使えてないだけなんじゃないかと思うんだけど、どうかな?

ichigo61
質問者

補足

見つけて頂いたものと同じメーカーのものなのですが、ちょっと定義が違っていて、 提供されているヘッダに、 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関数は頻繁に呼ばれるので、ダイアログを一時的に生成するのは、おかしいです。メンバー関数をうまく引き渡しできず、苦肉の策で書いた次第です。 まだ、問題は解決できていません。

回答No.5

結論から言えば、全体の設計が大きく間違っていなければ、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(); をおいておきます。

ichigo61
質問者

補足

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)
回答No.4

そこのコード片のどこで CFrrjiftestDlg::msubInit を呼び出しているんですか?

ichigo61
質問者

補足

msubInit は、OninitDialog の中で呼んでいます。

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.3

#1 への補足を見たが.... とりあえず落ち着け. 「(1)で、new したものが、(2)でクリアされてしまうので、(3)で使えない。」と書いているが, それはどう確認したの? そのプログラム片を見る限り, そもそも「(1) で new」などしていないようにしか読めないぞ.

ichigo61
質問者

補足

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% (1621/5657)
回答No.2

CFrrjiftestDlg::OnBnClickedButton1()での this をどうにかしてMyDataHandler()に教えてあげてください。

ichigo61
質問者

補足

その方法が分かればいいのですが、どう書いていいのやら。。。。

  • hitomura
  • ベストアンサー率48% (325/664)
回答No.1

void MyDataHandler(sFrameOfData* FrameOfData) { CFrrjiftestDlg dlg; dlg.sndrobot(); } CFrrjiftestDlg::sndrobot(); という呼び出し方をどうしてもしたければ、 class CFrrjiftestDlg : public CDialog { /* 中略 */ static void sndrobot(); }; とします。ただし、この場合静的でない(staticを付けずに宣言した)メンバ関数・メンバ変数は使用できません。

ichigo61
質問者

補足

教えていただいた方法で、コンパイルエラーはなくなりましたが、ちょっと問題が。。。 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)で使用できるようになるのでしょうか?

関連するQ&A

  • オーバーライドとオーバーロードについて

    1.CTestDlgクラスを作成 class CTestDlg : public CDialog { // コンストラクション public: BOOL Create(CWnd *pWnd); CWnd * m_pParent; CTestDlg(CWnd* pParent = NULL); // 標準のコンストラクタ・ ・ 2.メンバ関数の定義 BOOL CTestDlg::Create(CWnd *pWnd) { m_pParent = pWnd; BOOL bret = CDialog::Create( CTestDlg::IDD, m_pParent); if( bret == TRUE) { this->ShowWindow( SW_SHOW); } return bret; 以上のような場合において、 1.Create(CWnd *pWnd)は、引数が異なるため virtual BOOL Create( LPCTSTR lpszTemplateName, CWnd* pParentWnd = NULL ); をオーバーライドしたとは言わず、オーバーロードしたということで良いのでしょうか? 2.オーバーロードしたということであれば、 Create(CWnd *pWnd)と virtual BOOL Create( LPCTSTR lpszTemplateName, CWnd* pParentWnd = NULL ); の両方の関数が使えると思っていたのですが、後者方は引数が異なるとエラーが出て使えませんでした。 どうしてなのでしょうか? 以上、2点についてご教授ください。

  • クラスのメンバ関数の呼出しについて

    こんにちは。 初心者ですが、よろしくお願いします。 MFCを使用してダイアログベースのアプリケーションを作成しています。 <ヘッダ> class Sample : public CDialog { (略) public: int SampleA(CString); (略) <ソース> UINT SampleB(LPVOID pParam) { int n; n = Sample::SampleA(CStringA) ←エラー return 0; } メンバ関数ではない、SampleBから、上記のように呼出すと、「静的でないメンバ関数の中で呼び出しが正しくありません。」というエラーが表示されてしまいます。 ヘッダ内のメンバ関数宣言をstaticにすれば問題は解決できるのですが、このやり方しかないのでしょうか。 よろしくお願いします。

  • 通常関数とメンバー関数のやりとりでコンパイルエラー

    下記にあるようなプログラムをコンパイルしたら、下記のエラーになりました。 どこに問題があるのでしょうか? 「error C2227: '->SetValueXyzwpr2' : 左側がクラス、構造体、共用体、ジェネリック型へのポインタではありません。」 //frrjif.h class _DataPosReg : public COleDispatchDriver { // Operations public: BOOL SetValueXyzwpr2(long Index, float X, float Y, float Z, float W, float P, float R, float E1, float E2, float E3, short C1, short C2, short C3, short C4, short C5, short C6, short C7, short UF, short UT); }; //frrjiftestDlg.h #include "frrjif.h" class CFrrjiftestDlg : public CDialog { public: CFrrjiftestDlg(CWnd* pParent = NULL); // standard constructor virtual ~CFrrjiftestDlg(); protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support //}}AFX_VIRTUAL // Implementation _Core *pCore; _DataPosRegXyzwpr *pPosRegXyzwpr; _DataSysVarPos *pSysVarPos; }; //frrjiftestDlg.cpp #include "frrjiftestDlg.h" void MyDataHandler(sFrameOfData* FrameOfData) { CFrrjiftestDlg::pSysVarPos->SetValueXyzwpr2(X,Y,Z,W,P,R,E1,E2,E3,C1,C2,C3,C4,C5,C6,C7,UF,UT); //↑ここでコンパイルエラー //↑error C2227: '->SetValueXyzwpr2' : 左側がクラス、構造体、共用体、ジェネリック型へのポインタではありません。 } void CFrrjiftestDlg::OnBnClickedButton1() { Cortex_SetDataHandlerFunc(MyDataHandler); }

  • 親クラスのポインタで派生クラスの関数呼び出し

    下記のようなクラス構成があるとします。 説明のため簡略化しています。 [Test.h] class CParent { protected: int nParent; public: CParent(){nParent = 10;} ~CParent(){}; virtual int func1(){ // (*1) return nParent; } }; class CSub : public CParent { int m_nSub1; // 派生クラスにしかないメンバ変数 int m_nSub2; // 派生クラスにしかないメンバ変数 public: CSub(){m_nSub = 20;} ~CSub(){}; int func1(){ // (*3) return nParent*2; // 20 } // 派生クラスにしかないメンバ関数 int func2() // (*4) { m_nParent; // 10 return m_nSub1; // 不定値 } int SetData(int n) // (*5) { m_nSub2 = n; return m_nSub2; } }; [Test.cpp] void main() { CParent parent; // 親クラスのオブジェクト CParent* pParent = &parent; // 親クラスのオブジェクトを指すポインタ int nRet = 0; nRet = pParent->func1(); // (*1) // サブクラスのポインタ型にキャストする CSub* pSub = (CSub*)pParent; // (*2) nRet = pSub->func1(); // (*3) nRet = pSub->func2(); // (*4) nRet = pSub->SetData(60); // (*5) } (*3)ではpSubの指すオブジェクトが親クラス(CParent)のため、ポリモーフィズムのメカニズムに従ってCParent::func1()が呼ばれ10が返ってきます。ここまでは想定通りです。 次の(*4)ですが、これはCSub::func2()が呼ばれています。なぜこの呼び出しで子クラスの関数を呼ぶことが出来るのでしょうか? 実際その動作をさせたいのですが、なぜそうなるのかが分かりません。想定ではpSubが指す先は親クラスのため、子クラスにしかないメンバ関数func2()は呼べないはずです。 このコードでは、CSubのコンストラクタは通りませんので(そもそもCSub型のインスタンスは実体化していない)、(*4)の呼び出しでは不定値が返ります。また、(*5)は期待通り動作し、戻り値60が返っています。 これは危険な事をしているのでしょうか? 期待通りではあるのですが、なぜこのような動作になるのか理解できません。 上記のようなことをしたい場合、どのように記述するべきでしょうか?

  • メンバ関数(メソッド)をマルチスレッドにしたい

    環境はWinXPでVisual Studio 2005を使用しています。 C言語で関数をマルチスレッド化するにはこんな感じでOKでした。 // マルチスレッド関数 void Thread( void * ) { } void MainFunc() {   (HANDLE)_beginthread( Thread, 0, NULL ); } こんな風にスレッド関数をC++のメソッドに変えてうまくいくかと思い class Test_c { public:   void Thread( void * ); } ; // マルチスレッド関数 void Test_c::Thread( void * ) { } void MainFunc() {   Test_c t t;   (HANDLE)_beginthread( t.Thread, 0, NULL ); } とするとエラーが出てきてしまい、コンパイルが通りませんでした。 C++のメンバ関数をマルチスレッド関数としたい場合はどの様に書けばよいのでしょうか・・?

  • 引数付きコンストラクタでコンパイルエラー

    MFCダイアログベースアプリを作成しています。 開発環境はVC++2005です。 CtestDlgクラスのOnBnClickedOk()関数内での処理、 CtestDlg2 dlg( &hoge ); にてCtestDlg2ダイアログ起動し、CString型変数hogeを、 CtestDlg2クラスのコンストラクタに引数として渡したいのですが、 コンパイルエラーが出てしまい、何が原因か分かりません。 解決法をご存知の方おられましたら、お手数ですがご教授お願い致します。 【エラー内容】 error C2664: 'CtestDlg2 ::CtestDlg2(const CtestDlg2 &)' : 1 番目の引数を 'CString *__w64 ' から 'const CtestDlg2 &' に 変換できません。(新しい機能 ; ヘルプを参照) 理由: 'CString *__w64 ' から 'const CtestDlg2' へは 変換できません。 コンストラクタはソース型を持てません、またはコンストラクタの オーバーロードの解決があいまいです。 【CtestDlgクラス内宣言】 void CtestDlg::OnBnClickedOk(){ CString hoge = "aaa"; CtestDlg2 dlg( &hoge ); dlg.DoModal(); } 【CtestDlg2クラスコンストラクタ】 //CtestDlg2::CtestDlg2(CWnd* pParent /*=NULL*/) CtestDlg2::CtestDlg2(CString* st, CWnd* pParent /*=NULL*/) : CDialog(CtestDlg2::IDD, pParent), m_st(st) { } 【CtestDlg2クラスヘッダ内宣言】 public: CtestDlg2::CtestDlg2(CString* st, CWnd* pParent /*=NULL*/); CString* m_st;

  • ダイアログのOKボタンを押してウィンドウを生成する方法は?

    ダイアログのOKボタンを押すとウィンドウが生成する方法を教えてください。 MFCでプログラミングしてメインウィンドウをダイアロボックスにしています //アプリケーション class CMyApp : public CWinApp { public: virtual BOOL InitInstance(); }; //メインダイアログ class CMyDlg : public CDialog { public: CMyDlg(CWnd *pParentWnd=NULL); protected: virtual void OnOK(); virtual void OnCancel(); }; #include <afxwin.h> #include <afxdlgs.h> #include <string.h> #include "dlg.h" #include "resource.h" CMyApp myApp; BOOL CMyApp::InitInstance(){ m_pMainWnd = new CMyDlg; m_pMainWnd ->ShowWindow(m_nCmdShow); m_pMainWnd ->UpdateWindow(); return TRUE; } CMyDlg::CMyDlg(CWnd* pParent /*=NULL*/) { Create("MYDLG"); } としています。 ダイアログはできるのですが、ここからウィンドウを生成する方法を教えてください

  • constのついたメンバ関数

     こんにちは。 C++を勉強しているのですが疑問に思ったことがあります。 const指定したメンバ関数にメンバ変数の変更をすることはエラーになるはずなんですが、 下記にある(*m_pRefCnt)++; はコンパイルが通るようです。 なぜこの一文だけ通るのでしょうか? 以下にソースを添付しておきます。 #include <iostream> class hogeClass { private: int* m_pRefCnt; int val; void AddRef() const { (*m_pRefCnt)++; // これはOK? val = 100; // これは駄目 } void Release() { } public: explicit hogeClass(char* src = NULL) : val(0) { } int& GetRefCnt() { return *(m_pRefCnt); } virtual ~hogeClass() { Release(); } }; int main() { int c = 435, k = 222; using namespace std; hogeClass a; getchar(); return 0; } 分かる人がいたらよろしくお願いします。

  • 標準コンストラクタとDDX/DDVのサポート

    標準コンストラクタとDDX/DDV のサポートを行いたいんですが、MFCを使用せずに行えますか? 使用ツールはVC++2010 Expressです。 CPcmTestDlg(CWnd* pParent = NULL); virtual void DoDataExchange(CDataExchange* pDX); と、同じ動作ができるソースにしたいんですが…… 解る方がいらっしゃいましたら、是非教えてください。 よろしくお願いします。

  • C++の継承の曖昧さの解決について教えてください

    こんにちは。 よろしくおねがいします。 class bass { public:   virtual ~bass(){} }; class Ex1 : public bass{}; class Ex2 : public bass{}; class Ex3 : public Ex1, public Ex2{}; void hoge( bass* foo ){} void main() {   hoge( &Ex1() );   hoge( &Ex2() );   hoge( &Ex3() ); } でhoge( &Ex3() );の関数呼び出しで曖昧さが解決できないとコンパイルエラーが出てしまいます。 これを解決するにはどのように指定すればよいのでしょうか?

専門家に質問してみよう