プロが教える店舗&オフィスのセキュリティ対策術

クラスや構造体の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)));」
一応問題なく動いているようなのですが心配です。

よろしくお願いします。

A 回答 (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

以上です。
    • good
    • 0
この回答へのお礼

こんにちは。

>クラスのメンバ変数が10個近くあるということでしょうか?
「クラスのコンストラクタ時の引数」の意味のつもりでした。
言い方的に正しくなかったです。
混乱させてしまいすいません。

非常に分かりやすくサンプルコードまで書いて頂き、
ありがとうございます。

これを参考にもう一度自分のコードを組み直してみます。

お礼日時:2010/10/12 21:40

「クラス引数」って何でしょうか?


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

「クラス引数」×
「クラスのコンストラクタ時の引数」○
です。

後、初期化リスト、の意味をデフォルト引数と勘違いしていました。
ちゃんと書いてくれていたのにごめんなさい。
おっしゃる通り、初期化リストの方が便利です。使えそうです。

「tmp を作成する」の意味は#3の最初で書いて頂いた文の意味であっています。

重ね重ねありがとうます。

かなり勉強になりました。

お礼日時:2010/10/12 21:39

えぇと... やっぱり今一つ意味が分からんのだけど, ひょっとして「コンストラクタに渡した値を直接メンバ変数に設定できないか」ということ? つまり, 今の例だと


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 な参照を使ったり初期化リストを使ったりした方がいいと思うんだけど.... 今の場合については使わない理由もないし.
    • good
    • 0
この回答へのお礼

ありがとうございます。

今、自分が作成しているプログラムではクラス引数が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;

}
================================

お礼日時:2010/10/11 13:56

質問1 は意味がわかりません. 「tmp を作成する」とはどういうことでしょうか?


質問2 は... わざわざ new しなくてもいいのでは? new しなければメモリリークも起きえないのに.
    • good
    • 0
この回答へのお礼

testObjArray.push_back(Test("てすと1",1,true));
の形で渡せるんですね(^^;
ありがとうございます。勉強不足でした。

「tmp を作成する」で言いたかったのは
 Test(std::string tmp_sono1,int tmp_sono2,bool tmp_sono3){…
の様に、
一度「tmp_ほにゃらら」の各変数一度で受けてから
それぞれ
sono1=tmp_ほにゃらら;
の様に内部変数に渡すしか方法がないのでしょうか?
ということです。
説明不足ですいません。

他にも変な所があればご指摘して頂けると助かります。

お礼日時:2010/10/11 01:08

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

この回答への補足

下の
memory-leakは特に起こしていませんでした。

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

補足日時:2010/10/11 01:14
    • good
    • 0
この回答へのお礼

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

お礼日時:2010/10/11 01:01

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!