ページ 1 / 1
コントラスタに引数があるクラスの動的確保
Posted: 2017年10月07日(土) 21:06
by 遊び人
お世話になっております。
例えば以下のようなプログラムがあったとき、21行目にてクラスの動的確保を行っているのですが、コントラスタに引数が必要な場合、
以下のような書き方などではコンパイルエラーになってしまいます。
どのように書けばエラーにならないのかお教えください(初期化は何行になっても構いません)
コード:
#include <iostream>
#include <random>
using namespace std;
class A {
private:
int a;
public:
A(int num) : a(num) { }
void show_a() { cout << a << endl; }
};
int main()
{
int test_num = 5;
A *test;
random_device rand_num;
mt19937 mt(rand_num());
//こ↑こ↓---------------------------
test = new A[test_num](mt() % 5 + 1);
//-----------------------------------
for (int i = 0; i < test_num; i++) {
test[i].show_a();
}
delete[] test;
return 0;
}
Re: コントラスタに引数があるクラスの動的確保
Posted: 2017年10月07日(土) 23:11
by lunnear
コンストラクタに引数を設定するのではなく、初期化関数を用意して配列を作った後、個々に呼び出せばいい。
Re: コントラスタに引数があるクラスの動的確保
Posted: 2017年10月07日(土) 23:30
by 遊び人
回答ありがとうございます。
確かにそのようにすればプログラムは動きますね!
動的確保の場合コントラスタに引数があると難しいですか(´・ω・`)
Re: コントラスタに引数があるクラスの動的確保
Posted: 2017年10月08日(日) 00:10
by lunnear
すいませんが自分には動的配列を生成と同時に引数を渡す方法はわからないです。
もしかしたらあるかもしれませんが。
Re: コントラスタに引数があるクラスの動的確保
Posted: 2017年10月08日(日) 00:16
by みけCAT
生成と同時に初期化をするのはできなそうですが、plaement newというのを使うと(デフォルトコンストラクタで初期化した)後から引数付きのコンストラクタを利用して初期化出来るようです。
その13 引数付きコンストラクを持つクラスの配列を初期化する方法
Re: コントラスタに引数があるクラスの動的確保
Posted: 2017年10月08日(日) 01:47
by 遊び人
どちらにしてもデフォルトコントラスタは作らなければならないようですね・・・
どちらを使用するか迷いますが
以後plaement newを使用させていただきます。
皆さんありがとうございました!
コード:
#include <iostream>
#include <random>
#include <new>
using namespace std;
class A {
private:
int a;
public:
A() : a(0) { }
A(int num) : a(num) { }
void show_a() { cout << a << endl; }
};
int main()
{
int test_num = 5;
A *test;
random_device rand_num;
mt19937 mt(rand_num());
//こ↑こ↓---------------------------
test = new A[test_num];
for (int i = 0; i < test_num; i++) {
new(test + i) A(mt() % 5 + 1);
}
//-----------------------------------
for (int i = 0; i < test_num; i++) {
test[i].show_a();
}
delete[] test;
return 0;
}
Re: コントラスタに引数があるクラスの動的確保
Posted: 2017年10月08日(日) 18:11
by ISLe
遊び人 さんが書きました:どちらにしてもデフォルトコントラスタは作らなければならないようですね・・・
デフォルトコンストラクタは作らなくてもできます。
既存オブジェクトを上書きするのではなく、更地に構築します。
コード:
#include <iostream>
#include <random>
#include <new>
using namespace std;
class A {
private:
int a;
public:
A(int num) : a(num) { }
void show_a() { cout << a << endl; }
};
int main()
{
int test_num = 5;
char *buf;
A **test;
random_device rand_num;
mt19937 mt(rand_num());
buf = new char[sizeof(A) * test_num]; // 配置用メモリ領域確保
test = new A*[test_num]; // 各オブジェクトへのポインタ
for (int i = 0; i < test_num; i++) {
test[i] = new(buf + sizeof(A) * i) A(mt() % 5 + 1);
}
for (int i = 0; i < test_num; i++) {
test[i]->show_a();
}
for (int i = 0; i < test_num; i++) {
test[i]->~A(); // (必要なら)デストラクタは明示的に呼ぶ
}
delete[] test;
delete[] buf;
return 0;
}
Re: コントラスタに引数があるクラスの動的確保
Posted: 2017年10月09日(月) 04:03
by かずま
A *test; のままでもできますよ。
コード:
#include <iostream>
#include <random>
#include <new>
using namespace std;
class A {
private:
int a;
public:
A(int num) : a(num) { }
void show_a() { cout << a << endl; }
};
int main()
{
int test_num = 5;
A *test;
random_device rand_num;
mt19937 mt(rand_num());
test = reinterpret_cast<A*>(new char[sizeof(A) * test_num]);
for (int i = 0; i < test_num; i++)
new(test + i) A(mt() % 5 + 1);
for (int i = 0; i < test_num; i++)
test[i].show_a();
for (int i = 0; i < test_num; i++)
test[i].~A();
delete[] reinterpret_cast<char*>(test);
return 0;
}
Re: コントラスタに引数があるクラスの動的確保
Posted: 2017年10月09日(月) 15:57
by 遊び人
デフォルトコントラスタを作らなくてもできる方法があったんですね!
かずまさんのコードが綺麗で個人的に気に入りました。
ポインタって奥が深いですね。