C++ stringクラスのメンバ変数が表示できない理由を教えて下さい

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
naopon

C++ stringクラスのメンバ変数が表示できない理由を教えて下さい

#1

投稿記事 by naopon » 11年前

C++のテキストで多態性の例題を改造したのですが、stringクラスのメンバ変数が表示できなくなってしまいました。
テキストの記述はmain関数でいくつかの派生クラスのオブジェクトを作成し、そのポインタを基本クラスのポインタ型配列に代入して、メンバ関数を呼び出すというものです。
ポインタ型配列の初期値として、派生クラスのアドレスを設定するように変更してみると、
ShowData()関数を呼び出した時点でメンバ変数nameが空になっているようで、名前の所だけ何も表示されなくなりました。
なぜこのようなことになったのか教えていただけませんか。

コード:

class Jugyoin{
	public:
  	        int number;		// 社員番号
		string shimei;		// 氏名
		long kyuyo;		// 給与
		virtual void ShowData();	// メンバ変数の値を表示する
		Jugyoin();				// 引数のないコンストラクタ
		Jugyoin(int n, string s, long k);// 引数を持つコンストラクタ
};
// Yakuinクラスの定義
class Yakuin : public Jugyoin{
	 public:
		int kabu;			// 株式保有数
		void ShowData();
		Yakuin();
		Yakuin(int n, string s, long k, int kb);
};
// Kachoクラスの定義
class Kacho : public Jugyoin{
	public:
		int shuchohi;		// 出張費
		void ShowData();
		Kacho();
		Kacho(int n, string s, long k, int sh);
};
// Jugyoinクラスのメンバ関数の実装定義
void Jugyoin::ShowData()
{
	cout << "社員番号:" << number << "\n";
	cout << "氏名:" << shimei << "\n";
	cout << "給与:" << kyuyo << "\n";
}
Jugyoin::Jugyoin()
{
	number = 0;
	shimei = "未設定";
	kyuyo = 150000;
}
Jugyoin::Jugyoin(int n, string s, long k)
{
	number = n;
	shimei = s;
        kyuyo = k;
}

// Yakuinクラスのメンバ関数の実装定義
void Yakuin::ShowData()
{
	Jugyoin::ShowData();
	cout << "株式保有数:" << kabu << "\n";
}
Yakuin::Yakuin()
{
	kabu = 100;
}
Yakuin::Yakuin(int n, string s, long k, int kb):Jugyoin(n, s, k)
{
	kabu = kb;
}

// Kachoクラスのメンバ関数の実装定義
void Kacho::ShowData()
{
	Jugyoin::ShowData();
	cout << "出張費:" << shuchohi << "\n";
}
Kacho::Kacho()
{
	shuchohi = 10000;
}
Kacho::Kacho(int n, string s, long k, int sh):Jugyoin(n, s, k)
{
	shuchohi = sh;
}
int main()
{
	//	基本クラスのポインタの配列を作成する
	Jugyoin* p[6] = { &Yakuin(1111,"役員一郎",500000,1000), 
&Kacho(2222,"課長一郎", 350000,10000), 
			         &Kacho(3333,"課長次郎", 300000,5000),
                                 &Eigyoman(4444,"営業一郎",230000,1235),
				 &Eigyoman(5555,"営業次郎",250000,4567),
				 &Eigyoman(6666,"営業三郎",270000,6789)
	};
	//Jugyoin* p[6];

	// 派生クラスのオブジェクトを作成し、基本クラスのポインタに代入する
	//Yakuin y(1111,"役員一郎",500000,1000);
	//p[0] = &y;
	//Kacho b1(2222,"課長一郎", 350000,10000);
	//p[1] = &b1;
	//Kacho b2(3333,"課長次郎", 300000,5000);
	//p[2] = &b2;
	//Eigyoman e1(4444,"営業一郎",230000,1235);
	//p[3] = &e1;
	//Eigyoman e2(5555,"営業次郎",250000,4567);
	//p[4] = &e2;
	//Eigyoman e3(6666,"営業三郎",270000,6789);
	//p[5] = &e3;

	// メンバ関数を呼び出す
	for( int i = 0 ; i < 6 ; i++ ){
		p[i]->ShowData();
	}
}

Poco
記事: 161
登録日時: 14年前

Re: C++ stringクラスのメンバ変数が表示できない理由を教えて下さい

#2

投稿記事 by Poco » 11年前

main()関数内のローカル変数pの作成の仕方が悪いです。
naoponさんのコードの各クラスにデストラクタを追加しました。
ステップ実行でデストラクタが呼び出されるタイミングを見てください。
p->ShowData()が呼ばれる前に、デストラクタが呼ばれることに気付くと思います。

コード:

#include <string>
#include <iostream>

using namespace std;

class Jugyoin{
public:
	int number;     // 社員番号
	string shimei;      // 氏名
	long kyuyo;     // 給与
	virtual void ShowData();    // メンバ変数の値を表示する
	Jugyoin();              // 引数のないコンストラクタ
	Jugyoin(int n, string s, long k);// 引数を持つコンストラクタ
	virtual ~Jugyoin();
};
// Yakuinクラスの定義
class Yakuin : public Jugyoin{
public:
	int kabu;           // 株式保有数
	void ShowData();
	Yakuin();
	Yakuin(int n, string s, long k, int kb);
	virtual ~Yakuin();
};
// Kachoクラスの定義
class Kacho : public Jugyoin{
public:
	int shuchohi;       // 出張費
	void ShowData();
	Kacho();
	Kacho(int n, string s, long k, int sh);
	virtual ~Kacho();
};
// Jugyoinクラスのメンバ関数の実装定義
void Jugyoin::ShowData()
{
	cout << "社員番号:" << number << "\n";
	cout << "氏名:" << shimei << "\n";
	cout << "給与:" << kyuyo << "\n";
}
Jugyoin::Jugyoin()
{
	number = 0;
	shimei = "未設定";
	kyuyo = 150000;
}
Jugyoin::Jugyoin(int n, string s, long k)
{
	number = n;
	shimei = s;
	kyuyo = k;
}

Jugyoin::~Jugyoin()
{
	cout << "Jugyoin破棄します" << endl;
}

// Yakuinクラスのメンバ関数の実装定義
void Yakuin::ShowData()
{
	Jugyoin::ShowData();
	cout << "株式保有数:" << kabu << "\n";
}
Yakuin::Yakuin()
{
	kabu = 100;
}
Yakuin::Yakuin(int n, string s, long k, int kb) :Jugyoin(n, s, k)
{
	kabu = kb;
}
Yakuin::~Yakuin()
{
	cout << "Yakuin破棄します" << endl;
}

// Kachoクラスのメンバ関数の実装定義
void Kacho::ShowData()
{
	Jugyoin::ShowData();
	cout << "出張費:" << shuchohi << "\n";
}
Kacho::Kacho()
{
	shuchohi = 10000;
}
Kacho::Kacho(int n, string s, long k, int sh) :Jugyoin(n, s, k)
{
	shuchohi = sh;
}
Kacho::~Kacho()
{
	cout << "Kacho破棄します" << endl;
}

int main()
{
	//  基本クラスのポインタの配列を作成する
	Jugyoin* p[] = {
		&Yakuin(1111, "役員一郎", 500000, 1000),
		&Kacho(2222, "課長一郎", 350000, 10000),
		&Kacho(3333, "課長次郎", 300000, 5000),
	};

	// メンバ関数を呼び出す
	for (int i = 0; i < sizeof p / sizeof p[0]; i++){
		p[i]->ShowData();
	}
}

naopon

Re: C++ stringクラスのメンバ変数が表示できない理由を教えて下さい

#3

投稿記事 by naopon » 11年前

ありがとうございます。
名前だけが表示されなかったので、stringクラスのコンストラクタを調べたりしておりました。

Jugyoin* p[] = {&Yakuin(1111, "名前", 500000,1000), ・・・};
のような初期値設定の仕方では、&Yakuin(1111, "名前", 500000,1000)で一時的にオブジェクトが作成されて、そのアドレスが配列に格納され、一時的なオブジェクトは破棄されるということなのですね。
ポインタ型の配列に初期値を設定することは、できないのでしょうか。
このような場合、要素数が多くなると大変ですが、例題のようにオブジェクトを作成して、そのアドレスを1個1個の要素に代入するという方法しかないのでしょうか?

たびたび申し訳ありませんが、ご教授よろしくお願いいたします。

アバター
h2so5
副管理人
記事: 2212
登録日時: 14年前
住所: 東京
連絡を取る:

Re: C++ stringクラスのメンバ変数が表示できない理由を教えて下さい

#4

投稿記事 by h2so5 » 11年前

ポインタ型の配列でなければならない理由がよくわかりません。
いちおうnew演算子を使えばポインタ型でも初期化できますが、あとでdeleteする必要があるので二度手間です。

Poco
記事: 161
登録日時: 14年前

Re: C++ stringクラスのメンバ変数が表示できない理由を教えて下さい

#5

投稿記事 by Poco » 11年前

一つ一つ代入してください。
ただ、要素数が多くなると、初期データは外部(ファイルやDB)に配置して、コードに埋め込むことはなくなります。
加えて、配列ではなくstd::vectorを使うことになります。

かずま

Re: C++ stringクラスのメンバ変数が表示できない理由を教えて下さい

#6

投稿記事 by かずま » 11年前

naopon さんが書きました:このような場合、要素数が多くなると大変ですが、例題のようにオブジェクトを作成して、そのアドレスを1個1個の要素に代入するという方法しかないのでしょうか?
代入の代わりに初期化が使えます。

コード:

int main()
{
	Yakuin   y1(1111, "役員一郎", 500000,  1000);
	Kacho    k1(2222, "課長一郎", 350000, 10000);
	Kacho    k2(3333, "課長次郎", 300000,  5000);
	Eigyoman e1(4444, "営業一郎", 230000,  1235);
	Eigyoman e2(5555, "営業次郎", 250000,  4567);
	Eigyoman e3(6666, "営業三郎", 270000,  6789);
    Jugyoin* p[6] = { &y1, &k1, &k2, &e1, &e2, &e3 };
 
}
class Eigyoman はどこ?

naopon

Re: C++ stringクラスのメンバ変数が表示できない理由を教えて下さい

#7

投稿記事 by naopon » 11年前

h2so5様
>ポインタ型の配列でなければならない理由がよくわかりません。
テキストのポリモーフィズムの例題で
【オーバーライドによる多態性は、C++の言語仕様として「基本クラスのポインタに派生クラスのオブジェクトのポインタをフ代入できる」】
の確認としてテキストに掲載してありました。
基本クラスJugyoinのポインタ配列pに派生クラスのポインタを代入してポインタ経由でメンバ関数ShowDataを呼び出すとそれぞれの派生クラスでオーバーライドしたメンバ関数が呼び出されるという実験例だと解釈しております。
new演算子での初期化&deleteの方法、ありがとうございます。

Poco様
たびたびありがとうございました。ファイルからの読み込み&vectorに挑戦してみます。

かずま様
>class Eigyoman はどこ?
申し訳ありません。同じようなクラスでコードが長くなるので省いたのですが、
main関数から省くのを忘れておりました。
例題のやり方よりも、提示していただいたコードの方がすっきりですね。
ありがとうございました。

閉鎖

“C言語何でも質問掲示板” へ戻る