我有一段代码将大量计算应用于一组数据。这些数据是在一个类中组织的,主要由标量和浮点数和双精度数组成。问题是类上的变量取决于输入文件结构,即文件A可能有10个标量变量,B可能有20个数组。如何创建抽象来处理这种异构数据?
我想过为每个不同的输入A和B创建一个类Data和一个特定的数据,它继承自Data。但是我有一个大问题:
在代码中我只想在
中将数据集作为Data类来处理vector<Data> datas;
Data d = new Data();
datas.push_back(d);
我不想做
vector<Data> datas;
Data d = new A();
datas.push_back(d);
但这意味着父类将访问变量,构造函数等的子类,如果可能的话,我现在不会这样做(请注意,应用程序只读取文件A或B,不是在同一个执行中,我没有在编译时设置哪个并且只将A或B类添加到代码中的问题)
P.S。:在原始代码中,由非计算机科学家编写,他们将创建Data类和#include&#34; variables.cxx&#34;在其声明中。它显然有效但应该不惜一切代价避免......
答案 0 :(得分:0)
您需要一个指向基类的指针数组。这允许向量使用一种固定大小(指向基类的指针),但该类型代表不同大小的所有对象。
std::vector<base*> datas;
datas.push_back(new derived);
如果你有c ++ 11,那么vector可以为你管理内存:
std::vector<std::unique_ptr<base>> datas;
datas.push_back(std::make_unique<derived>());
答案 1 :(得分:0)
在C ++中使用动态绑定,允许您通过父类型的指针访问子类中的函数(构造函数除外)。这是一个示例:
class Data
{
public:
virtual void func() = 0;
};
class A : public Data
{
public:
void func();
};
class B : public Data
{
void func();
};
然后你可以像这样处理数据:
vector<Data*> datas;
Data *d = new A();
d->func();//do something, for example read data from files
datas.push_back(d);
答案 2 :(得分:0)
正如您所说,您很乐意在编译时选择类型的一个选项是在数据类型上模拟代码:
template<typename Data>
void doComputations() {
std::vector<Data> datas;
Data d;
datas.push_back(d);
}
doComputations<A>();
然后,您不需要基础Data
类只是A
和B
共享的隐式接口。但这可能意味着你的许多代码必须被模板化,这可能不是你想要的。
如果要利用Data
基类的运行时多态行为,则需要存储指针向量。
填充向量的一种方法是使用单独的向量拥有A
和B
,然后使用一个Data
原始指针向量来进行计算:
std::vector<A> a_datas;
std::vector<B> b_datas;
a_datas.push_back(A{});
a_datas.push_back(A{});
b_datas.push_back(B{});
std::vector<Data*> datas;
for (auto& a : a_datas)
datas.push_back(&a);
for (auto& b : b_datas)
datas.push_back(&b);
doComputations(datas);
或者更灵活的方法是在堆上分配对象并使用一个智能指针向量管理它们:
struct Data {
public:
virtual ~Data(){}
//...
};
struct A : Data { /* ... */ };
struct B : Data { /* ... */ };
std::unique_ptr<Data> loadData() {
if ( condition )
return std::make_unique<A>();
else
return std::make_unique<B>();
}
}
std::vector<std::unique_ptr<Data>> datas;
datas.push_back(loadData());
datas.push_back(loadData());
doComputations(datas);