私は、基本データ型へのポインタを保持する構造体データを設計する必要があります。ユーザーは、このデータ構造体のオブジェクトを簡単に作成し、メモリ管理の問題の多くを処理せずに回り越えることができます。多型データを扱うデータクラスを設計する正しい方法
構造がほとんど作成されていません。正しい処理方法を提案してください。
struct BaseData {
enum DataType { DATATYPE_1, DATATYPE_2 };
virtual ~BaseData() { cout << "BaseData Dtor" << endl; }
};
struct DataType1 : BaseData {
virtual ~DataType1() { cout << "DataType1 Dtor" << endl; }
};
struct DataType2 : BaseData {
virtual ~DataType2() { cout << "DataType2 Dtor" << endl; }
};
struct Data {
Data() { cout << "Data Ctor" << endl; }
Data(const Data& o) {
if (o.baseData->type == BaseData::DATATYPE_1) {
baseData = new DataType1;
*(static_cast<DataType1*>(baseData)) = *(static_cast<DataType1*>(o.baseData));
}
else if (o.baseData->type == BaseData::DATATYPE_2) {
baseData = new DataType2;
*(static_cast<DataType2*>(baseData)) = *(static_cast<DataType2*>(o.baseData));
}
}
virtual ~Data() {
cout << "Data Dtor" << endl;
delete baseData; //here it results in segmentation fault if object is created on stack.
baseData = NULL;
}
BaseData* baseData;
};
vector <Data> vData;
void addData(const Data& d) { cout << "addData" << endl; vData.push_back(d); }
クライアントコードは以下のようになります。
int main()
{
{
DataType1 d1;
d1.type = BaseData::DATATYPE_1;
Data data;
data.baseData = &d1;
addData(data);
}
{
BaseData* d2 = new DataType2;
d2->type = BaseData::DATATYPE_2;
Data data;
data.baseData = d2;
addData(data);
delete d2;
d2 = NULL;
}
{
Data data;
data.baseData = new DataType1;
static_cast<DataType1*>(data.baseData)->type = BaseData::DATATYPE_1;
addData(data);
delete data.baseData;
data.baseData = NULL;
}
}
ブロック1とブロック2のコードは、二重削除のためにクラッシュします。これらのユースケースをすべて適切に処理するにはどうすればよいですか。
私が考えている方法の1つは、privateを使用してbaseDataポインタを非表示にして、ユーザーにメソッドsetBaseData(const BaseData& o)
をstruct Data
に提供することです。
void setBaseData(const BaseData& o) {
cout << "setBaseData" << endl;
if (o.type == BaseData::DATATYPE_1) {
baseData = new DataType1;
*(static_cast<DataType1*>(baseData)) = static_cast<const DataType1&>(o);
}
else if (o.type == BaseData::DATATYPE_2) {
baseData = new DataType2;
*(static_cast<DataType2*>(baseData)) = static_cast<const DataType2&>(o);
}
}
setBaseData()では、セグメンテーションフォールトを避けることができ、ユーザーは自分が好きな構造化データのオブジェクトを自由に作成できます。
これらのクラスを設計する方法はありますか?