ページ 11

クラスの宣言の仕方について

Posted: 2016年12月07日(水) 14:41
by pocket
お世話になっております.

C++暦は約2年になります.
ふと疑問に思ってソースコードを書いたところ,エラーが出ました.
その原因についてお教えいただければ幸いです.

コード:

#include <random>
#include <iostream>
using namespace std;

class Sample{
  public:
    Sample(int rand):menber(rand){};
    
    int getRand();
    int menber;   
};
int Sample::getRand(){
    std::random_device rand;
    return(rand()%100);   
}

int main(){
    //Sample sampleA;
    //sampleA=Sample(sampleA.getRand());
    Sample sampleA = Sample(sampleA.getRand());     
    cout<<sampleA.menber<<endl;
}
一行でクラスの宣言をした場合は,適切に動作しますが,
二行に分けた場合(ソースコード内でコメントしている部分)は,エラーが出ます.

実行環境のリンクを載せます.
http://melpon.org/wandbox/permlink/QJonnkRMCRN8cgZH

new演算子で試してみてもうまく動作しませんでした.
解決策を,この問題が起こる原因について解答いただければと思います.
よろしくお願いいたします.
よろしくお願いいたします.

Re: クラスの宣言の仕方について

Posted: 2016年12月07日(水) 16:12
by Rittai_3D
デフォルコトンストラクタを追加したら動きました。

コード:

#include <random>
#include <iostream>
using namespace std;

class Sample{
  public:
    Sample() = default;
    Sample(int rand):menber(rand){};

    int getRand();
    int menber;   
};
int Sample::getRand(){
    std::random_device rand;
    return(rand()%100);   
}

int main(){
    Sample sampleA;
    sampleA=Sample(sampleA.getRand());
    //Sample sampleA = Sample(sampleA.getRand());     
    cout<<sampleA.menber<<endl;
}
http://melpon.org/wandbox/permlink/6pDDH3CkAUx2GADk

Re: クラスの宣言の仕方について

Posted: 2016年12月07日(水) 16:17
by C6b14
参考までに。想像ですが、こういう事をされたかったのではないですか。

コード:

#include <random>
#include <iostream>
using namespace std;

class Sample {

public:
	Sample() :menber(123) {}//コンストラクター:イニシャライザ
	
	int getRand();//getメソッド
	//int menber;
private:
	std::random_device rand;//rand=乱数生成器
	int menber;//メンバー変数
};
int Sample::getRand() {//getメソッド
	menber = rand();
	return(menber % 100);
}

int main() {
	Sample *sampleA;//宣言
	sampleA = new Sample();//インスタンス生成
	//Sample *sampleA = new Sample();

	cout << sampleA->getRand() << endl;
}
なぜイニシャライザがいるのか?

Re: クラスの宣言の仕方について

Posted: 2016年12月07日(水) 16:54
by usao
オフトピック
>Sample sampleA = Sample(sampleA.getRand());

どちらかというと,こっちの書き方が気になる.
getRand()呼ぶ時点では,インスタンスsampleAは生成されていないように見えるのだけど…

Re: クラスの宣言の仕方について

Posted: 2016年12月07日(水) 16:57
by あんどーなつ
pocket さんが書きました:お世話になっております.
C++暦は約2年になります.
ふと疑問に思ってソースコードを書いたところ,エラーが出ました.
その原因についてお教えいただければ幸いです.
宜しければその疑問も聞かせていただけますか?

Sample sampleA; がダメな理由ですが、これは、
Sample sampleA(); や Sample sampleA{}; と同じ意味だからです。つまり、この引数を宣言してからmain関数が終わるまでの寿命を持つSample型のオブジェクトを引数なしで生成しているためです。

クラスにコンストラクタを記述しなかった場合は、デフォルトコンストラクタが生成されるので、Sample sampleA; はOKとなりますが、引数が異なるコンストラクタを定義しているので、デフォルトコンストラクタが生成されず、Sample sampleA;がNGとなっています。

Sample *sampleA = new Sample(sampleA.getRand()); でもOKです。ただしこの場合はmain関数の最後にdelete sampleA; と書く必要があります(今回の場合は本当は書かなくてもよいのですが、書かないとトイレの戸を開けっ放しにしているように思われるからnewといえばdeleteを心がけましょう)。

Re: クラスの宣言の仕方について

Posted: 2016年12月07日(水) 17:24
by pocket
みなさん

複数の返答ありがとうございます.
疑問点とは,usaoさんがおっしゃっていることについてです.

私が見たプログラムで,以下のように,定義した変数(sampleA)自身の関数(getRand)を自分の引数(コンストラクタ)に使っていたので,実際に動作するかの検証をしたかったです.

コード:

Sample sampleA = Sample(sampleA.getRand());  
あんどーなつさんのおっしゃることを参考に,今回の問題と原因をまとめたいと思います.
まず,自身でint引数をとるコンストラクタを新しく作成した場合は,デフォルトコンストラクタが作成されないため,
Sample sampleA;の部分でエラーが出ていました.この文でデフォルトコンストラクタ(引数なしコンストラクタ)を呼ぶためです.
なので,デフォルトコンストラクタを明示的に作成することで解決しました.
(デフォルトコンストラクタをSample() = default;の様に書けるのですね.初めて知りました.)

私の疑問点についてお時間を割いていただき,本当にありがとうございました.
以上で,解決とさせていただきます.