クラスや構造体の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)));」
一応問題なく動いているようなのですが心配です。
よろしくお願いします。
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
以上です。
こんにちは。
>クラスのメンバ変数が10個近くあるということでしょうか?
「クラスのコンストラクタ時の引数」の意味のつもりでした。
言い方的に正しくなかったです。
混乱させてしまいすいません。
非常に分かりやすくサンプルコードまで書いて頂き、
ありがとうございます。
これを参考にもう一度自分のコードを組み直してみます。
No.4
- 回答日時:
「クラス引数」って何でしょうか?
さておき.
「内容の値も状況によりバラバラな為、このようなクラスの場合、初期化リストがあまり有効でないです。」
という状況では「コンストラクタで引数を受け取ってメンバ変数に代入する」しかないんじゃないかなぁ... というか, 直接代入できたとしても無意味な感じがします. 「直接代入できる」ためには「コンストラクタの引数とメンバ変数がそれなりに対応する」必要があるんだけど, もしそうなら初期化リストが使えるように思えるので.
あと, 確かに「各メンバ変数に代入するためだけの関数」を作るのは変ですね. 値のチェックをするとか「与えられた値から各メンバ変数に適切な値を計算する」のならともかく, 値をそのまま代入するだけなら単純に代入した方がましだと思います.
結局のところ「tmp を作成する」の意味はやっぱりよくわからんのだなぁ.... #3 の最初の文の意味でいい?
「クラス引数」×
「クラスのコンストラクタ時の引数」○
です。
後、初期化リスト、の意味をデフォルト引数と勘違いしていました。
ちゃんと書いてくれていたのにごめんなさい。
おっしゃる通り、初期化リストの方が便利です。使えそうです。
「tmp を作成する」の意味は#3の最初で書いて頂いた文の意味であっています。
重ね重ねありがとうます。
かなり勉強になりました。
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 な参照を使ったり初期化リストを使ったりした方がいいと思うんだけど.... 今の場合については使わない理由もないし.
ありがとうございます。
今、自分が作成しているプログラムではクラス引数が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;
}
================================
No.2
- 回答日時:
質問1 は意味がわかりません. 「tmp を作成する」とはどういうことでしょうか?
質問2 は... わざわざ new しなくてもいいのでは? new しなければメモリリークも起きえないのに.
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起こしてませんか?
この回答への補足
下の
memory-leakは特に起こしていませんでした。
は
memory-leakは起こしているかもしれませんが、
問題は出ていませんでした。
の誤りです。
ちゃんと正しくdeleteすべきです。
memory-leakは特に起こしていませんでした。
が、
確かにちゃんとdeleteしないといけませんね。
ありがとうございます。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# 質問です 下記のコードを分かりやすく解説お願いします 初心者です #include ‹stdio.h 3 2022/05/26 22:03
- Java java final 1 2022/06/10 22:49
- C言語・C++・C# c言語の問題です 課題1 (二分探索木とセット) 大きさ size の配列 array を考える。す 2 2023/01/10 21:08
- C言語・C++・C# C言語プログラム変更 2 2022/12/21 15:03
- Visual Basic(VBA) VBA GetAttrについて教えてください 2 2022/12/22 15:25
- Visual Basic(VBA) VBA シート上にドロップダウンリストを作り、予め指定値をセットしたいのですが 1 2023/03/25 15:15
- Excel(エクセル) エクセルのマクロが途中の行から適用されない 2 2022/07/09 20:25
- Excel(エクセル) エクセルのマクロについて教えてください。 1 2023/02/06 13:01
- Java JavaのSingletonパターンのprivateの持つ意味が分かりません。 5 2022/06/12 10:38
- Excel(エクセル) エクセルVBAでオブジェクトが必要です 2 2022/09/10 16:37
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
DWORDの実際の型は何でしょうか
-
構造体
-
typedef enumの使い方を教えて...
-
関数の実体定義にヘッダファイ...
-
void func( void )について
-
long型の定数の末尾にLを付ける...
-
C++でboolにintの値を代入する...
-
C言語のコンパイルエラー
-
intとINTの違いは?
-
プログラムの中で別のmainを呼...
-
2重定義って??
-
配列を用いない最大値の求め方
-
staticで初期化した変数(?)を使...
-
C++ クラスをメンバにもつクラ...
-
C++で構造体のコピーはできても...
-
ハンドルされていない例外が発...
-
フィボナッチ数列 c言語
-
【#define】 defineで定義した...
-
DDVによるメッセージの変更
-
構造体の要素すべてに対する四...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
DWORDの実際の型は何でしょうか
-
visualstudio C# テキストボッ...
-
2重定義って??
-
long型の定数の末尾にLを付ける...
-
C++のfor文について
-
typedef enumの使い方を教えて...
-
関数の実体定義にヘッダファイ...
-
変数の型を定義しなかった場合...
-
ハンドルされていない例外が発...
-
C++でboolにintの値を代入する...
-
main.c:7:43: warning: implici...
-
プログラムの中で別のmainを呼...
-
【#define】 defineで定義した...
-
void func( void )について
-
構造体の要素すべてに対する四...
-
C++の(左辺値)参照を参照渡し
-
構造体の宣言でエラーが出ます。
-
main()とint main(void)の違い
-
intとINTの違いは?
-
エラー「invalid conversion fr...
おすすめ情報