クラスや構造体のarrayを作成する方法とコンストラクタの引数渡し

このQ&Aのポイント
  • クラスや構造体のarrayを作成する方法とコンストラクタの引数渡しについて質問です。
  • 質問1:コンストラクタ時、クラス内の変数へ引数の値を渡す方法について教えてください。
  • 質問2:push_back時、クラスをインスタンスしてvectorに渡す方法についても教えてください。
回答を見る
  • ベストアンサー

クラスや構造体のarrayを作りたい。

クラスや構造体のarrayを作りたい。 クラスや構造体のarrayを作りたいのですが、 以下の方法で正しいのでしょうか? ==================================== #include <string> #include <vector> class Test{ public:   std::string sono1;   int sono2;   bool sono3;   //コンストラクタ   Test(std::string tmp_sono1,int tmp_sono2,bool tmp_sono3){     sono1=tmp_sono1;     sono2=tmp_sono2;     sono3=tmp_sono3;   } }; void main(){   std::vector<Test> testObjArray;   testObjArray.push_back(*(new Test("てすと1",1,true)));   testObjArray.push_back(*(new Test("てすと2",2,false))); } ==================================== 質問1: コンストラクタ時、クラス内の変数へ引数の値を渡す時、 上記のようにtmpを作成する以外の方法はありますか? 質問2: push_back時、クラスをインスタンスしてvectorに渡すにはこのような記述であってるのでしょうか? 「testObjArray.push_back(*(new Test("てすと1",1,true)));」 一応問題なく動いているようなのですが心配です。 よろしくお願いします。

質問者が選んだベストアンサー

  • ベストアンサー
noname#144013
noname#144013
回答No.5

こんにちは。 > 今、自分が作成しているプログラムではクラス引数が10個近くあり、 クラスのメンバ変数が10個近くあるということでしょうか? 変数に関連性があるのでしたら、バラバラな変数にするよりも全部纏めて 一つの構造体にするのは如何でしょうか? 構造体にすれば、コンストラクタの引数で値を渡す場合でも一つの構造体 を渡せば済むと思います。 もっともその場合でも、引数に渡すための構造体を予め用意して、その 構造体に初期値を設定しておく必要はありますので、バラバラな引数に 値を渡すのと大して手間は変わらないかもしれません。 何れにせよ、何処かで初期値を設定する処理は必要だと思います。 ■サンプルソース ========================= #include <iostream> #include <string> #include <vector> using namespace std; //データ構造体の定義 typedef struct HOGE {   string strName;   int nData1;   bool bData2;   int nData3;   int nData4;   int nData5; } T_HOGE, *PT_HOGE; //== Testクラスの定義 == class Test { public:   //メンバデータ   T_HOGE m_tHoge;   //コンストラクタ   Test(T_HOGE &tHoge) : m_tHoge(tHoge){}   //メンバデータ表示   void DispHoge(); }; //== Testクラスの関数(本体) == //メンバデータ表示 void Test::DispHoge() {   cout << "Name = " << m_tHoge.strName << endl;   cout << "Data1= " << m_tHoge.nData1 << endl;   cout << "Data2= " << (m_tHoge.bData2? "True":"False") << endl;   cout << "Data3= " << m_tHoge.nData3 << endl;   cout << "Data4= " << m_tHoge.nData4 << endl;   cout << "Data5= " << m_tHoge.nData5 << endl; } int main(void) {   int i;   T_HOGE tHoge;   vector<Test> testObjArray;   vector<Test>::iterator it;   //testObjArrayへのデータ追加(1個目)   tHoge.strName = "dog";   tHoge.nData1 = 1;   tHoge.bData2 = true;   tHoge.nData3 = 123;   tHoge.nData4 = 1234;   tHoge.nData5 = 12345;   testObjArray.push_back(Test(tHoge));   //testObjArrayへのデータ追加(2個目)   tHoge.strName = "cat";   tHoge.nData1 = 2;   tHoge.bData2 = false;   tHoge.nData3 = 234;   tHoge.nData4 = 2345;   tHoge.nData5 = 23456;   testObjArray.push_back(Test(tHoge));   //testObjArrayのデータ表示   for(i=0, it=testObjArray.begin(); it!=testObjArray.end(); ++i, ++it){     cout << (i+1) << "個目:" << endl;     (*it).DispHoge();   }   //testObjArrayのデータ消去   testObjArray.clear();   return 0; } ========================= <実行結果> 1個目: Name = dog Data1= 1 Data2= True Data3= 123 Data4= 1234 Data5= 12345 2個目: Name = cat Data1= 2 Data2= False Data3= 234 Data4= 2345 Data5= 23456 以上です。

kuwezi
質問者

お礼

こんにちは。 >クラスのメンバ変数が10個近くあるということでしょうか? 「クラスのコンストラクタ時の引数」の意味のつもりでした。 言い方的に正しくなかったです。 混乱させてしまいすいません。 非常に分かりやすくサンプルコードまで書いて頂き、 ありがとうございます。 これを参考にもう一度自分のコードを組み直してみます。

その他の回答 (4)

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

「クラス引数」って何でしょうか? さておき. 「内容の値も状況によりバラバラな為、このようなクラスの場合、初期化リストがあまり有効でないです。」 という状況では「コンストラクタで引数を受け取ってメンバ変数に代入する」しかないんじゃないかなぁ... というか, 直接代入できたとしても無意味な感じがします. 「直接代入できる」ためには「コンストラクタの引数とメンバ変数がそれなりに対応する」必要があるんだけど, もしそうなら初期化リストが使えるように思えるので. あと, 確かに「各メンバ変数に代入するためだけの関数」を作るのは変ですね. 値のチェックをするとか「与えられた値から各メンバ変数に適切な値を計算する」のならともかく, 値をそのまま代入するだけなら単純に代入した方がましだと思います. 結局のところ「tmp を作成する」の意味はやっぱりよくわからんのだなぁ.... #3 の最初の文の意味でいい?

kuwezi
質問者

お礼

「クラス引数」× 「クラスのコンストラクタ時の引数」○ です。 後、初期化リスト、の意味をデフォルト引数と勘違いしていました。 ちゃんと書いてくれていたのにごめんなさい。 おっしゃる通り、初期化リストの方が便利です。使えそうです。 「tmp を作成する」の意味は#3の最初で書いて頂いた文の意味であっています。 重ね重ねありがとうます。 かなり勉強になりました。

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

えぇと... やっぱり今一つ意味が分からんのだけど, ひょっとして「コンストラクタに渡した値を直接メンバ変数に設定できないか」ということ? つまり, 今の例だと Test(std::string sono1,int sono2,bool sono3) のようにできれば「いちいちメンバ変数に設定するだけの文を書かなくていい」から楽じゃんとか, そういうこと? もしそうなら, そんなことはできません. (コンストラクタを含む) メンバ関数にローカルな変数 (仮引数や局所変数) はクラス (のオブジェクト) が持つメンバ変数とは厳密に区別されますから, 「いったん仮引数で受け取り, その値を使ってメンバ変数を設定する」しかありません. ところで, Test(const std::string &tmp_sono1, int tmp_sono2, bool tmp_sono3) : sono1(tmp_sono1), sono2(tmp_sono2), sono3(tmp_sono3) { } のように const な参照を使ったり初期化リストを使ったりした方がいいと思うんだけど.... 今の場合については使わない理由もないし.

kuwezi
質問者

お礼

ありがとうございます。 今、自分が作成しているプログラムではクラス引数が10個近くあり、 内容の値も状況によりバラバラな為、 このようなクラスの場合、初期化リストがあまり有効でないです。 あと、setSono1,2,3等、値をセットする関数を書くと、引数の数が多い場合 プログラムがとても長くなってしまいます。そういう物なんでしょうか? (質問のプログラムの様に、コンストラクタ内で直接値をセットするのは 邪道?あまりしないのが普通ですか?) とりあえず指摘された場所を直してみました。 こんな感じで良いでしょうか? ================================ #include <string> #include <vector> class Test{ public: std::string sono1; int sono2; bool sono3; //コンストラクタ Test(const std::string &tmp_sono1,int tmp_sono2,bool tmp_sono3){ setSono1(tmp_sono1); setSono2(tmp_sono2); setSono3(tmp_sono3); } void setSono1(const std::string &tmp_sono1){sono1=tmp_sono1;} void setSono2(int tmp_sono2){sono2=tmp_sono2;} void setSono3(bool tmp_sono3){sono3=tmp_sono3;} }; int main(void){ std::vector<Test> testObjArray; testObjArray.push_back(Test("てすと1",1,true)); testObjArray.push_back(Test("てすと2",2,false)); return 0; } ================================

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

質問1 は意味がわかりません. 「tmp を作成する」とはどういうことでしょうか? 質問2 は... わざわざ new しなくてもいいのでは? new しなければメモリリークも起きえないのに.

kuwezi
質問者

お礼

testObjArray.push_back(Test("てすと1",1,true)); の形で渡せるんですね(^^; ありがとうございます。勉強不足でした。 「tmp を作成する」で言いたかったのは  Test(std::string tmp_sono1,int tmp_sono2,bool tmp_sono3){… の様に、 一度「tmp_ほにゃらら」の各変数一度で受けてから それぞれ sono1=tmp_ほにゃらら; の様に内部変数に渡すしか方法がないのでしょうか? ということです。 説明不足ですいません。 他にも変な所があればご指摘して頂けると助かります。

回答No.1

newしたインスタンスをdeleteしてませんけど、memory-leak起こしてませんか?

kuwezi
質問者

お礼

memory-leakは特に起こしていませんでした。 が、 確かにちゃんとdeleteしないといけませんね。 ありがとうございます。

kuwezi
質問者

補足

下の memory-leakは特に起こしていませんでした。 は memory-leakは起こしているかもしれませんが、 問題は出ていませんでした。 の誤りです。 ちゃんと正しくdeleteすべきです。

関連するQ&A

  • vectorを引数とする関数

    以下のようなプログラムにおいて、 #include <stdio.h> #include <cstdlib> #include <iostream> #include <vector> #include <fstream> #include <sstream> #include <map> using namespace std; double func(std::vector<double> *tmp2); int main(){ vector <double> tmp; tmp.resize(0); tmp.push_back(0.12458); tmp.push_back(-12.45); tmp.push_back(4.253); cout << func(&tmp) << endl; return 0; } double func(std::vector<double> *tmp2){ return tmp2[1]; } vector tmpをfuncに渡して、tmp[1]、すなわち、 -12.45が出力されるようにしたいと思います。 ですが、どうしてもコンパイルエラーが残ります。 どのようにすればよいでしょうか?

  • STL vectorの初期化

    STL vectorの初期化についてなんですが 以下のようなクラスのprivateなメンバ変数としてvectorを定義し それをメソッド内のループ処理にて初期化しながら使用したいのですが 初期化の仕方が分かりません。コンストラクタを呼べば初期化されるようですが 以下のようにヘッダとソース内で2度同じような宣言をしてしまっても問題ないのでしょうか? //=== test.h === class test { private : vector<int> array; public : int fnc(); }; //=== test.c === int fnc() { for (int i = 0; i < 10; i++) { //★ここで初期化したい vector<int> array;  ←これで問題ないか? for (int j = 0; j < 10; j++) { array.push_back( md ); } } } C#などでは宣言とインスタンス生成を別に分けられたのですがC++も同様の事が出来るのでしょうか? 一応「array = new vector<int>;」といれて見たのですがエラーが出ました。

  • std::lower_boundについて

    こんにちは。 std::vector< int* > IntArray; IntArray.push_back( new int( 0 ) ); IntArray.push_back( new int( 2 ) ); IntArray.push_back( new int( 1 ) ); IntArray.push_back( new int( 6 ) ); IntArray.push_back( new int( 5 ) ); IntArray.push_back( new int( 7 ) ); というint型のポインタが格納されているIntArrayを bool cmp( const int* lhs, const int* rhs ) {   return *lhs < *rhs; } std::sort( IntArray.begin(), IntArray.end(), cmp ); として並べ替えたとします。 そこで新しく new int( 4 )をソートされた順番を壊さない位置に挿入したいと思いlower_boundを使用しようと思いました。 しかし、lower_boundの使い方がいまいちわかりません。 int *p = new int( 4 ); bool cmp2( const int* lhs, const int* rhs ) {   return *lhs < *rhs; } std::lower_bound(  IntArray.begin(),  IntArray.end(),  p,  cmp2 ); 上記のように使用すればこの場合だと変数pを挿入する位置が返ってくるのでしょうか? 間違えているとしたら、どのように修正すれば変数pを挿入できる位置が返ってくるように書き直すことができるでしょうか?(むしろそういった実装は可能なのでしょうか) よろしくお願いします。 今回は特殊ケースでの問題ですのでint* pをintに修正する、挿入してから再度ソートする、といったことはなしでお願いします。あくまでもlower_boundで実装する場合のコードについてでよろしくお願いします。 /*   VisualStudio 2008 academic edition   Window7 64bit */

  • std::stringの継承

    #include <iostream> #include <string> class test : public std::string{ }; int main() { test tmp; tmp = "aaa"; } tmp = "aaa";ですが test::operator =(char *) が定義されていないとでますが何故なんでしょうか? string(basic_string)でoperator=が定義されていると思うのですが、 演算子の定義は継承されないのでしょうか。

  • ArrayクラスとtoStringについて

    問題集で次のプログラムを見掛ました。 public class Main{  public static void main(String args[]){   int[] array = new int[0];   System.out.println(array);  } } これを実行するとprintlnメソッドで toStringメソッドが呼び出されますが、 ArrayクラスはObjectクラスを継承しているため、 toStringメソッドもObjectクラスから継承されているので、 結果として、配列の要素数が0であっても、 エラー等が発生せずハッシュコードが表示される、ということです。 ObjectクラスのtoStringメソッドが ハッシュコードを返すものであるのは理解できます。 でも、なぜ要素数が1以上で何かしらの要素が存在する場合は、 ハッシュコードが返らないのでしょうか? 詳しい方、解説をお願いします。

  • shared_ptr クラスについて

    shared_ptrクラスを使いたいのですが、使えません、どうしてでしょうか?ソースはこれです。 #include<iostream> #include <string> #include <fstream> #include<memory> using namespace std; class SMonster{ string name; int power; public: SMonster(); SMonster(int p); ~SMonster(){ }; void SetPower(int p); int GetPower(SMonster& t)const; void walk(const string& str); int GetPoint(void)const; }; class B {}; class D : public B {}; int main(void) { shared_ptr<D> sp0(new D); SMonster m(200); SMonster n(100); std::cout<<m.GetPower(m)<<std::endl; std::cout<<n.GetPower(n)<<std::endl; ShowWindow(10); }

  • C++ STL vectorの使い方

    こんばんは。 C++のstd::vectorに関する質問です。 vectorをポインタ渡しにしたときに メンバにアクセスする方法を知りたいのですが・・・ 以下ソースの☆の部分をどう記述したらよいでしょう? #include <vector> typedef struct test {  char name[10];  char id[2]; } TEST; void funcVectorTest( std::vector<TEST> *a); int main(){  std::vector<TEST> a;  int i;  TEST foo= {"Taro","0"};  a.push_back(foo);  printf("%s",a[0].name);  a.push_back(foo);  printf("%s",a[1].name);  funcVectorTest(&a);//vectorのアドレス渡しテスト  printf("%s", a[2].name);//vectorのアドレス渡し確認  return 0; } void funcVectorTest( std::vector<TEST> *a) {  int i;  int cnt;  TEST *b;  b = new TEST[3];  TEST foo= {"Taro","0"};  a->push_back(foo);  cnt = a->size();  for( i = 0; i < cnt;i++){  //以下でa[i]のnameにアクセスしたいのですがうまくいっていません。  //☆strcpy( b[i].name, a[i]->name );  }  delete[] b; } お分かりになる方、お知恵をお貸し下さい(><) vectorについて最近知ったばかりでいまいち使い方が 分かっていない部分があるので このやり方がまずいということであれば教えていただけると 助かります。 よろしくお願いしますm( _ _ )m

  • ヘッダーファイルがインクルードされない(?)

    ダイアログ上のボタンをクリックすると指定されたテキストファイルをオープンし、 ファイルの内容をスペースで区切って格納するプログラムを http://oshiete1.goo.ne.jp/kotaeru.php3?q=474452 こちらを少し変えて作ったのですが、 コンパイル・デバッグを行なうと 'std' : 識別子がクラス名でも名前空間名でもありません。 'vector' : 定義されていない識別子です。 'ofstream' : 定義されていない識別子です。 と言ったようなエラーになってしまいます。 必要なヘッダーファイルはインクルードされているはずなのですが・・・。 この原因は何故でしょうか? /**********プログラムソース**********/ #include <iostream> #include <fstream> #include <string> #include <vector> #include <utility> #include "stdafx.h" #include "SCHEDULE.h" #include "SCHEDULEDlg.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif // ~中略~ void CSCHEDULEDlg::OnReq() {    typedef std::pair<std::string,std::string> item;    std::vector<item> participation;    std::ofstream file(dataFile.txt);    std::string line;    while ( std::getline(file,line) ) {      std::string::size_type pos = line.find(' ');      participation.push_back(item(line.substr(0,pos), line.substr(pos+1)));    }    for ( int i = 0; i < participation.size(); ++ i) {      std::cout << "result = " << participation[j] << "]\n";    } }

  • VectorなどSTL?テンプレートの使い方

    戻り値がポインタの場合、関数から抜け出すと値の保証が無いので、それを使用する場合は、変数にコピーして使うと値は残る(アクセス可能)と理解しています。 char tmp[128]; strcpy(tmp, test()); それで、次のような vector??を使った場合、表示の場合は問題ないかもしれませんが、その後、値を使い続ける場合、ポインタのままでよいのか疑問に思っています。 以下のソースは勝手気ままに記述したものですが、 VC++6でエラーなく動作(とりあえず動く)しているのですが、今後発生する問題など知りたいです。 #include "stdafx.h" #include <string> #include <iostream> #include <vector> #include <sstream> using namespace std; class A { string str; vector<A *> v_cls; public: A(){ } // デフォルトコンストラクタが必要? A(string s){ str = s; } void PrintData(void){ // 表示 cout << str << endl; } // 1から9までの[0]-[9]の文字列を作成 vector<A *> ArraySet(void){ stringstream ss; for (int i=0; i < 10; i++){ ss.str(""); ss << "function [" << i << "]\n"; v_cls.push_back( new A( ss.str() ) ); } return v_cls; } }; void main(void){ // 1から9までの[0]-[9]の文字列を作成 // これは問題ないと思う vector<A *> v; stringstream ss; for (int i=0; i < 10; i++){ ss.str(""); ss << "[" << i << "]\n"; v.push_back( new A( ss.str() ) ); } v[1]->PrintData(); v[3]->PrintData(); ////cout << v.size(); // クラス自身にvector配列?を返す処理 // とりあえず動いているだけ??? A x; vector<A *> ret = x.ArraySet(); // このような代入でも問題ないのでしょうか? ret[5]->PrintData(); // 表示だけなので、問題なし? ret[0]->PrintData(); // vやret, xの解放仕方とタイミングはどうすればよいのでしょうか? }

  • Vectorクラスの使い方

    いつもお世話になっております。 Vector vector = new Vector(); String array[] = new String[11]; vector.addElement(array) for( int i = 0; i1 < vector.size(); i++) { String str = (String)vector.get(i); System.out.println(str); } 11の配列にデータ(String)を入力し(ここでは省略)、11すべてをVectorへいれ、String型で取り出したいのですがエラーになります。 System.out.println(vector1.get(i));だと文字化けします。 アドバイスお願いします。そういったことを書いてあるサイト等ご存知でしたらお願いします。

    • ベストアンサー
    • Java

専門家に質問してみよう