トップページ > 過去ログ > 記事閲覧
オブジェクト生成について
名前:葡萄球 日時: 2009/12/25 00:03

C++での事なのですが クラス内で他のクラスのオブジェクトのメンバ関数を使いたいのですがなかなか上手く行かなくて、 「'関数名'の左側はクラス、構造体、共用体でなければなりません」と表示されてしまいます。 このような場合はどのような原因によって起こるのでしょうか? エラーの出る今のコードは ヘッダAのクラスをヘッダBのpublicでオブジェクト生成して、ソースCでメンバ関数を使っています。 すみません。書き終わった後見たらDXライブラリ関係無いですね。

Page: 1 | 2 |

Re: オブジェクト生成について ( No.5 )
名前:らり 日時:2009/12/25 11:42

>ちなみに >.cpp > >m_status.getPosition(&mx,&my); >はコンストラクタで生成しています。 この部分の意味が少し分かりませんが・・・ コンパイル時にそれ以外にエラーはでていませんか? Statusオブジェクトの生成に失敗しているか、 C.cppからm_statusが見えていないか、 どちらかだと思います。 とりあえず、 A.cpp void Status::getPosition( int *px, int *py) { if( px ) *px = m_x; if( py ) *py = m_y; } B.h Status m_status; int Bint_test;      //<-追加 C.cpp Status m_status_test;      //<-追加 m_status_test.getPosition(&mx,&my);//<-追加  Bint_test+=10; //<-追加 m_status.getPosition(&mx,&my); としてみて、B.hが見えているか&Statusクラスが生成されているのか、確かめてみてはどうでしょう。
Re: オブジェクト生成について ( No.6 )
名前:いっち 日時:2009/12/25 11:51

想像ですが、構成はこんな感じではないでしょうか? (A.hと"ほにゃらら"クラスの存在は私の推測です) A.h ... Statusクラスの宣言 A.cpp ... Statusクラスメンバの定義 (A.hをインクルード) B.h ... "ほにゃらら"クラスの宣言 (A.hをインクルード) C.cpp ... "ほにゃらら"クラスメンバの定義 (B.hをインクルード) "ほにゃらら"クラスのコンストラクタでStatus::getPosition関数を呼んでいる
Re: オブジェクト生成について ( No.7 )
名前:葡萄球 日時:2009/12/25 12:27

らりさん返信ありがとうございます。 追加をしてみたところ、 エラー 1 error C2065: 'Bint_test' : 定義されていない識別子です。 との表示がC.cppの方で増えました。エラーは上に書いてある2つと増えたBint_test~の3つのみです。 いっちさん返信ありがとうございます。 構想はいっちさんの推測通りです。もっと詳しく書くべきでしたね。すみません。
Re: オブジェクト生成について ( No.8 )
名前:いっち 日時:2009/12/25 13:36

C.cppで"ほにゃらら"クラスのコンストラクタの定義を行っていると思いますが、 その定義の関数名の前にスコープ解決演算子(::)がついているか確認してください。 ほにゃらら::ほにゃらら( void ) { int mx, my; m_status.getPosition(&mx,&my); return; }
Re: オブジェクト生成について ( No.10 )
名前:葡萄球 日時:2009/12/25 14:05

いっちさん返信ありがとうございます。 ::は付いていました。再度書いてみましたが、やはり変わりません。
Re: オブジェクト生成について ( No.11 )
名前:らり 日時:2009/12/25 14:12

う〜ん Bint_testが使えないということは、B.hがインクルードできていないのでしょう。 1. C.cppでincludeするファイル名が間違っている 2. 編集しているB.hとは別の同名ファイルが存在し、そちらをincludeしている 今思いつくのはこれくらいでしょうか・・・ *追記 確か、ヘッダファイルで実体を定義するのはご法度だったかと思います。 B.hではextern宣言でm_statusは宣言しておき、実体はcppファイルで宣言すべきだったかと。 ttp://homepage2.nifty.com/well/Header.html
Re: オブジェクト生成について ( No.12 )
名前:葡萄球 日時:2009/12/25 15:38

らりさん返信ありがとうございます。 サイト拝見させてもらいました。 ヘッダファイルで実体を定義するのはご法度だったんですね! externを使ってみたらエラーは無くなりました! 本には.hに実体定義してあったんでできると思ってました。 長々と付き合ってもらい本当にありがとうございました!
Re: オブジェクト生成について ( No.13 )
名前:いっち 日時:2009/12/25 15:52

問題が解決したようでなによりなのですが、 m_statusは"ほにゃらら"くらすのメンバ変数ではなく、 グローバル変数だったのでしょうか? できればソースを拝見したいのですが・・・。
Re: オブジェクト生成について ( No.14 )
名前:葡萄球 日時:2009/12/25 17:33

B.hの事でしょうか? 少し省略していますがこんな感じです。 B.h #pragma once class Chara { //メンバ関数////////////////////// public: //Chara(); void getPosition(int *px,int *py); //メンバ変数// public: //ステータスオブジェクト生成// Status m_status; };
Re: オブジェクト生成について ( No.15 )
名前:いっち 日時:2009/12/25 17:51

わざわざ返答ありがとうございます。 それで、(No.14)からどの部分をexternにしたのでしょうか? また、コンストラクタのChara関数がコメントになっているのはなぜでしょうか? しつこくてすみません。 私の知識が間違っているのであれば修正したいのです。よろしくお願いします。
Re: オブジェクト生成について ( No.16 )
名前:葡萄球 日時:2009/12/25 20:54

できたと思ってたんですが ただの変数を作っていました。 //Chara()はまだ作っていないのでコメントになっています。 まだ良くわかってないのですが、参考にしている本にはStatus m_statusはやはりクラスのメンバに書いてあるので何か他に方法があるかも知れません。
Re: オブジェクト生成について ( No.17 )
名前:いっち 日時:2009/12/25 22:39

> //Chara()はまだ作っていないのでコメントになっています。 私の認識では、Chara()内でエラーが発生していると思っていたのですが違うのでしょうか? やはり、ソース全体を見せて頂くのが早いと思うのですが、 とりあえず、こんな感じであろうというソースを作ってみました。 意味のないプログラムですが、おそらくコンパイルは通るはずです。(mainが無いですが) 便宜的にCharaクラスのコンストラクタも作ってあります。 下記のソースと比較して、ここが違うとか、ここがおかしいといった部分があれば教えてください。 /** A.h ***************************************/ #pragma once class Status { int m_x, m_y; public: Status( void ) { m_x = 640/2, m_y = 480/2; }; void getPosition( int *px, int *py); }; /** A.cpp *************************************/ #include "A.h" void Status::getPosition( int *px, int *py) { if( px ) *px = m_x; if( py ) *py = m_y; } /** B.h ***************************************/ #include "A.h" class Chara { //メンバ関数////////////////////// public: Chara(); void getPosition(int *px,int *py); //メンバ変数// public: //ステータスオブジェクト生成// Status m_status; int mx, my; }; /** C.cpp *************************************/ #include "B.h" Chara::Chara( void ) { m_status.getPosition( &mx, &my ); mx /= 2; my /=2; return; } void Chara::getPosition( int *px, int *py ) { if( px ) *px = mx; if( py ) *py = my; return; }
Re: オブジェクト生成について ( No.18 )
名前:葡萄球 日時:2009/12/26 00:21

いっちさん返信ありがとうございます。 自分のプログラムに合わせて書いたところ 今度はキッチリ動いてくれました! 自分の為にサンプルのプログラムまで作って貰って本当に感謝の言葉も出ないくらいです。 しかし未熟者の自分にはどう処理されているのかがよくわからない箇所があります。 よろしければ質問させてください。 /** A.h ***************************************/ #pragma once class Status { int m_x, m_y;//(1)ここにint宣言する意味(これはpublicになるのでしょうか?) public: Status( void ) { m_x = 640/2, m_y = 480/2; }; void getPosition( int *px, int *py); }; /** A.cpp *************************************/ #include "A.h" void Status::getPosition( int *px, int *py) { if( px ) *px = m_x; if( py ) *py = m_y; } /** B.h ***************************************/ #include "A.h" class Chara { //メンバ関数////////////////////// public: Chara(); void getPosition(int *px,int *py); //メンバ変数// public: //ステータスオブジェクト生成// Status m_status; int mx, my;//(2)ここのm_x,m_yからの変更理由 }; /** C.cpp *************************************/ #include "B.h" Chara::Chara( void ) { m_status.getPosition( &mx, &my ); mx /= 2; my /=2; return; } void Chara::getPosition( int *px, int *py )//(3)同じような処理のgetPosition関数を作らなければいけない理由 { if( px ) *px = mx; if( py ) *py = my; return; } どうかよろしくお願いします。
Re: オブジェクト生成について ( No.19 )
名前:いっち 日時:2009/12/26 01:00

うまく動作したとのことで良かったです。 葡萄球さんも丸一日お疲れ様でした。 ちょっと眠いので質問には明日(今日?)回答させて頂きます。
Re: オブジェクト生成について ( No.20 )
名前:葡萄球 日時:2009/12/26 01:07

いっちさん長々と付き合わせてしまってすみません。 返信は暇なときにでいいのでゆっくり休んでくださいね。
Re: オブジェクト生成について ( No.21 )
名前:らり 日時:2009/12/26 11:03

私の返信がいらぬ混乱を招いてしまっていましたね。申し訳ありません。 実体定義うんぬんの話は、直接原因になりえない話だったので、 それで解決することはありえなかったと思います。 私はグローバル変数だと思い込んでいたのですが、クラスメンバの宣言は、 実体ではないので、最初から問題なかったようですね。
Re: オブジェクト生成について ( No.22 )
名前:葡萄球 日時:2009/12/26 12:43

らりさん返信ありがとうございます。 申し訳ないなんてそんな。話に付き合ってもらって、 自分の知らないヘッダファイルでの実態定義の話を教えてくれたり本当にありがとうございます。 これからの作業にとても有意義な話でした。
Re: オブジェクト生成について ( No.23 )
名前:いっち 日時:2009/12/26 14:45

回答です。(ただし、私は動けばなんだっていいじゃん主義寄りなプログラマなのでかなりいい加減です) (1) classにおける既定のアクセス制御はprivateですので、ここのm_x、m_yはprivateになります。 メンバ変数をprivateにする理由の教科書的な回答としては、以下のような感じだと思います。 ・クラス外部からメンバ変数への不用意なアクセスを防ぐため ・メンバ変数の値を保障するため ・保守・移植性を高めるため・・・等々 入門書などでは初心者は慣れるまでとにかくpublicにしましょうと言っていたりしますが、 一般的な設計ではメンバ変数はprivateにし、外部からのアクセスにはアクセス用の メンバ関数(いわゆるSetter/Getter)をpublicで定義するというのが基本だと思います。 (Statusクラス、CharaクラスのgetPosition関数もGetterと言えます) 外部から直接アクセスできないと最初はまどろっこしく感じますが、ソースが 大きくなればなるほど開発効率が良くなるはずです。 (2) (No.2)(No.4)のレスからCharaクラスにはmx、myというメンバ変数が使われているのではないかと 推測してこの変数名になりました。 ここの変数名がm_x、m_yでも(Statusクラスのメンバ変数の名前と重複していても)問題ないです。 ただし、似たような変数名がいっぱいあるとわかりにくくはなります。 (3) (No.14)のレスにおいてCharaクラスにgetPositionが宣言されていたので、 サンプルにも書いてみました。 私にはStatusクラスやCharaクラスの意味や役割を推測することはできても断定はできませんので、 getPosition関数の意味、役割、必要性についても判りかねます。 CharaクラスにもgetPosition関数が必要かどうかは葡萄球さんが決めることです。 という前提で考えると、(No.18)のソースでは微妙な感じです。 これはCharaクラスのmx、myの意味と必要性や、m_statusのアクセス制御によっても変わってきます。 m_statusをprivateにした場合、外部からm_status.getPosition関数は呼べなくなるので、 CharaクラスでgetPosition関数を定義する意味はあります。 見当違いな回答をしていたらすみません。 疑問点やおかしなところがあればご指摘ください。
Re: オブジェクト生成について ( No.24 )
名前:いっち 日時:2009/12/26 15:09

(1)の具体例としてサンプルを書いてみました。 //-- Sample ----------------------------------------------------------------// class Screen { private: int m_w, m_h; public: Screen( void ) { m_w = 0; m_h = 0; }; bool GetSize( int &width, int &hight ); // Getter bool SetSize( const int width, const int hight ); // Setter }; bool Screen::GetSize( int &width, int &hight ) { width = m_w; hight = m_h; return true; } bool Screen::SetSize( const int width, const int hight ) { if ( (width < 0 || 640 <= width) || (hight < 0 || 480 <= hight) ) return false; // 不正な値ははじく m_w = width; m_h = hight; return true; } //---------------------------------------------------------------- Sample --// m_wとm_hの値はコンストラクタとSetSize関数によって保障されていますので、 外部からGetSize関数で値を取得した際に範囲のチェックをする必要がありません。 また、将来的にm_wとm_hの値をfloat型で管理する必要が(そんな事があるかないかは別として) できた場合、Screenクラスの内部を変更するだけで、外部のコードに変更を加える必要がありません。 例えばGetSize関数を以下のようにします。 bool Screen::GetSize( int &width, int &hight ) { // m_wとm_hはfloat型に変更済み width = (int)m_w; hight = (int)m_h; return true; // 関数名、引数、戻り値に変更がないので外部の変更は必要なし } 詳しくは専門の書籍や、Webをご覧になって下さい。
Re: オブジェクト生成について ( No.25 )
名前:葡萄球 日時:2009/12/26 21:35

いっちさん返信ありがとうございます。 解説も詳細まで書いてあってとてもわかりやすかったです。本当に助かりました!

Page: 1 | 2 |