- ベストアンサー
C++勉強中なんですが
クラス等を使ってソースを書く練習中なのですが、思ったように結果が出ません。 #include<iostream> #include<string> using namespace std; class Cats { private://クラス「Cats」の中でのみ使う文字列の入れ物変数「name」を作る string name; public://クラス「Cats」の外からでも引数で呼び出せば使える Cats(string x)//クラスCatsの関数Cats(コンストラクタ)を使いますよって宣言 { name=x;//8行目で作った文字列の入れ物に変数xを入れる } void naku()//voidの意味が正確には分からないけど、何も返さないって意味らしいので、何も返さないnakuって関数を作る { cout<<"にゃっふぅーん、ボク、"<<name<<"ってゆーの。よろしくネ!"<<endl;//関数nakuが呼び出されると文字列を表示する } }; int main()//全体のプログラム { string x;//まず文字列の入れ物になる変数xを作る cout<<"今日新たな家族になるにゃんこが産まれました。"<<endl; cout<<"名前を決めてあげましょう!"<<endl; Cats aisatsu(x);//クラスCatsのメンバーaisatsuを作る(中身は文字列の変数x) cin>> x;//変数xにキーボードで書いた文字列を入れる aisatsu.naku();//メンバー関数のaisatsuがグローバル関数(クラスの外からでも呼べるはずw)nakuを呼び出す } cin>>x;で入力した文字がnameに代入されてないのか、表示されません・・・。 もし分かる方いたら是非教えていただきたいです。 あと、コメントアウトしてる部分なんですが、ここもおかしい認識があればご指摘いただきたいです。
- みんなの回答 (4)
- 専門家の回答
質問者が選んだベストアンサー
#2です。 #2の私の回答への補足にnery1024さんが書いたとおりで、OKです。 あと、クラスを定義するとき、この場合は、1つのファイルにすべてを書いていますが、ヘッダーファイルという(*.h)別のファイル内に記述することが多いです。 なので、クラスのメンバ変数・関数の宣言だけをヘッダーに書き、 その関数の内容については、*.cpp内に書くことが多いのです。 そのとき、そのcppファイル内で、クラスを定義したヘッダーをincludeすればよいのです。 この場合ですと、 Cats.hに #ifdef __Cats_ //ヘッダを多重includeするときには必ず必要です #define __Cats_ //この行も class Cats{ private: string name; public: Cats(); Cats(string x); void naku(); }; #endif //最後にこの行も必要です を書き、 Cats.cpp に #include <iostream> #include "Cats.h" using namespace std; Cats::Cats(){ } Cats::Cats(string x){ name=x;//8行目で作った文字列の入れ物に変数xを入れる } void Cats::naku(){ cout<<"にゃっふぅーん、ボク、"<<name<<"ってゆーの。よろしくネ!"<<endl; } を書き、main.cppにmain関数を書けばよいです。 #include<iostream> #include<string> #include "Cats.h" using namespace std; int main()//全体のプログラム { string x;//まず文字列の入れ物になる変数xを作る cout<<"今日新たな家族になるにゃんこが産まれました。"<<endl; cout<<"名前を決めてあげましょう!"<<endl; cin>> x;//変数xにキーボードで書いた文字列を入れる Cats aisatsu(x);//クラスCatsのメンバーaisatsuを作る(中身は文字列の変数x) aisatsu.naku();//メンバー関数のaisatsuがグローバル関数(クラスの外からでも呼べるはずw)nakuを呼び出す return 0; // これを付け足してください }
その他の回答 (3)
- Tacosan
- ベストアンサー率23% (3656/15482)
コンストラクタでメンバー name に値を設定するときには Cats(string x) : name(x) { } のように「初期化」をする方がよいです. デフォルトコンストラクタは不要なら定義しなくていいです. ちなみに「_+大文字」とか「__」とかで始まる識別子を使うのは危険かもしれない. おっととと, なんでクラス名が Cats と複数形なんだろう?
お礼
>Cats(string x) >: name(x) >{ >} 回答ありがとうございます。 このソースを処理が終わったあとあたりに書くと初期化するって意味なんですかね? Catsと複数形にしたのは、勉強してて参考にしてるサイトに、クラスは色んなところに使いまわせるのが便利。みたいな説明を見たので、今回は使いまわさないだろうけど、使いまわすの前提で名付けました・・・。 使いまわすような事があると、恐らくは初期化したほうが良いとかになってくると勝手に予想させていただくとして、この質問回答はずっと残りそうなので、そのときがきたらTacosanの回答を参考にさせていただきます! あと、大文字から始まるのはやめたほうが良いんですね。 了解しました。
- kopanda116
- ベストアンサー率37% (88/232)
main関数内の、cin>>x; の部分がおかしいです。 Catsクラスの定義する前に入れてあげてください。 int main()//全体のプログラム { string x;//まず文字列の入れ物になる変数xを作る cout<<"今日新たな家族になるにゃんこが産まれました。"<<endl; cout<<"名前を決めてあげましょう!"<<endl; cin>> x;//変数xにキーボードで書いた文字列を入れる Cats aisatsu(x);//クラスCatsのメンバーaisatsuを作る(中身は文字列の変数x) aisatsu.naku();//メンバー関数のaisatsuがグローバル関数(クラスの外からでも呼べるはずw)nakuを呼び出す } でいいです。 あと、Cats aisatsu(x);はインスタンスの定義部分です。 Cats(string x);でコンストラクタを設定していますが、 しかし、普通、Cats();でデフォルトコンストラクタというのを定義しておかなければなりません。警告が出る可能性があります。 コンストラクタ定義部分の、コメントに「//8行目で作った文字列の入れ物に変数xを入れる」とありますが、このようにして関数を定義したいのであれば、コンストラクタで定義するべきではないと思います。 なぜなら、コンストラクタは、クラスの初期化のときに、どのような処理を行うかを決めるのがコンストラクタであるからです。 だから、Catsクラスのメンバ関数にsetString(string x)関数を定義して、データをCatsクラスに入れた方がよいのではないかと思います。 また、クラスの定義部分に、普通は関数を書かないです。 ですから、クラスの定義は、 class Cats{ private: string name; public: Cats(); Cats(string x); void naku(); }; として、main()関数の前くらいに、 Cats::Cats(){ } Cats::Cats(string x){ name=x;//8行目で作った文字列の入れ物に変数xを入れる } void Cats::naku(){ cout<<"にゃっふぅーん、ボク、"<<name<<"ってゆーの。よろしくネ!"<<endl; } を書いておくべきだと、思います。 ここに書いたのは、あくまで、私個人のコーディング慣習ですから、このような書き方があるというように理解してほしいです。
補足
とても興味深いのですが、理解しきれてません。 main関数の前にとの事ですが、ソースを書いてみますね。 #include<iostream> #include<string> using namespace std; class Cats{ private: string name; public: Cats();//ここで関数Catsを使うよって意味かな← Cats(string x);//Catsの中身は文字列xだよ← void naku();//なにも返さない関数nakuを使うよ }; ここまでで、←の部分は、まずからっぽの関数を作る事で、今の自分には分からないのですが、主にどういった時にそう記述したほうが良いのでしょうか? 続きは、main関数の前とあるのは、 Cats::Cats(){ } Cats::Cats(string x){ name=x; } void Cats::naku(){ cout<<"にゃっふぅーん、ボク、"<<name<<"ってゆーの。よろしくネ!"<<endl; } ここまで書いた後に、 int main(){ string x; ・ ・ ・ の様に記述すればいいのでしょうか?
- kmee
- ベストアンサー率55% (1857/3366)
> Cats aisatsu(x);//クラスCatsのメンバーaisatsuを作る(中身は文字列の変数x) の時点でx(この時点で空文字列)を使用してCatsクラスのインスタンスaisatsuが作成されているので > cin>> x;//変数xにキーボードで書いた文字列を入れる としたところでaisatsuには影響はない。(aistau.nakuはコンストラクタで代入したまま=空文字)
お礼
なるほど。 要するに、既にからっぽの変数を読み込んでるから、あとから変数に文字を入力したとしても、反映されないで関数nakuを呼び出してたって事ですか。 わかりやすかったですありがとうございました!
お礼
なるほど。 めちゃくちゃわかりやすいです。 ヘッダーファイルを出力するやり方とか、#ifdefとかはまだ覚えてないので、もう少し勉強が進んでからこの回答を参考にさせていただきますね。 return 0; は了解です。 ありがとうございました!