创建自定义类型对象的向量
Creating a vector of custom type objects
当我试图编译我所写的这段代码时,我得到了一些非常令人困惑的编译错误。这个想法是创造一个对象"分子",它有一个类型为"原子"的向量。每个原子从包含原子的x、y、z坐标及其z值的文件中读取。下面是我的代码示例。我已经把我的错误追溯到向量,所以我在下面展示了与它相关的所有代码。这个程序有点大,而且它以前没有Atom类(我实现了原子向量来取代嵌套数组,该数组在分子类中保存几何形状,我试图学习如何使用向量)。
我将vector初始化为分子类的私有成员,名称为atoms,类型为Atom,
class Molecule {
private:
std::vector<Atom> atoms;
// other declarations to follow
}
然后在分子类的构造函数中,我从文件中读取原子的数目,并将向量原子的大小调整为那个数目
file.open("geom.dat", ios::in);
if(file.is_open())
{
file >> natom;
atoms.resize (natom);
然后继续读取同一个文件,在文件的每行向vector添加一个原子。
while(!file.eof())
{
int a;
double b,c,d;
file >> a >> b >> c >> d;
Atom A(a,b,c,d);
atoms.push_back(A);
}
我在编译时收到的错误对我来说看起来像胡言乱语,它们引用了我没有编写的代码行。下面是一个例子
In file included from molecule.cpp:3:
In file included from /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/c++/v1/iostream:38:
In file included from /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/c++/v1/ios:216:
In file included from /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/c++/v1/__locale:15:
In file included from /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/c++/v1/string:439:
In file included from /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/c++/v1/algorithm:627:
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/c++/v1/memory:1456:36: error: no matching
constructor for initialization of 'Atom'
::new ((void*)__p) _Tp();
是否有问题与我的向量声明或我如何填充它。如果矢量不是我的编译错误的来源,我可以发布更多的代码,但这是我唯一改变的一方。
As Requested The Atom class:头文件:
class Atom
{
private:
int Zval;
double x;
double y;
double z;
public:
Atom(int zv, double xcart, double ycart, double zcart);
~Atom();
int get_Zval();
double get_x();
void ch_x(double val);
double get_y();
void ch_y(double val);
double get_z();
void ch_z(double val);
};
和原子类的源文件:
Atom::Atom(int zv, double xcart, double ycart, double zcart)
: Zval(zv), x(xcart),y(ycart), z(zcart) { }
int Atom::get_Zval(){ return Zval; }
double Atom::get_x() { return x; }
void Atom::ch_x(double val) { x+= val; }
double Atom::get_y(){ return y; }
void Atom::ch_y(double val) { y+= val; }
double Atom::get_z() { return z; }
void Atom::ch_z(double val) { z+= val; }
编译器正在您的Atom
类中寻找默认构造函数,但它没有默认构造函数。需要默认构造函数的原因是:
atoms.resize (natom);
resize()
如果新容器的大小大于当前容器的大小,则向vector中添加新元素,并且这些新元素是默认构造的。
你真正想要的是reserve()
:
atoms.reserve (natom);
简单地分配内存用于存储元素,但实际上并不添加任何元素。如果使用resize()
,最终添加的原子数量是输入文件中原子数量的两倍—一半是默认构造的,与文件数据无关,另一半是根据文件数据值构造的。
或者,完全删除resize()
/reserve()
,让push_back()
在需要时重新分配向量。但是,由于您提前知道要添加多少原子,因此使用reserve()
是一个好方法,因为向量只需要分配一次(除非在加载文件后添加更多原子)。
您显然已经解决了您发现的问题。现在让我来帮你解决一个你还没有意识到的问题。
我看到你们目前的设计有两个相当严重的问题。首先,您的Molecule类对Atom类的内部细节了解得太多了(特别是如何从文件中读取Atom数据)。其次,你的分子类正在从它的函数中的文件中读取一个分子,但是从文件中读取数据实际上应该在流提取器中进行。我会这样组织:
class Atom {
int Zval;
double x, y, z;
public:
Atom() : Zval(0), x(0), y(0), z(0) {}
friend std::istream &operator>>(std::istream &is, Atom &a) {
return is >> Zval >> x >> y >> z;
}
};
class Molecule {
std::vector<Atom> atoms;
public:
friend std::istream &operator>>(std::istream &is, Molecule &m) {
int size;
is >> size;
atoms.reserve(size);
std::copy_n(std::istream_iterator<Atom>(is),
size,
std::back_inserter(atoms));
return is;
}
};
这样,如何从文件中读取Atom的细节就留在Atom类中。Molecule类只处理要读取的若干个原子,然后再读取这些原子。
至于如何使用它,你可以这样读一个分子:
std::ifstream in("Molecule.txt");
Molecule m;
in >> m;
关于它在做什么和为什么:分子的提取操作符(operator>>
)从文件中提取分子的数据。它通过读取一个计数,然后从文件中读取原子的数量来实现这一点。Atom的提取操作符只是从文件中提取一个Atom的数据,然后返回。
file >> a >> b >> c;
根据cplusplus.com,向量包含项的副本。您需要声明一个公共复制构造函数来实现这一点,并声明一个默认构造函数来实现内存分配。它似乎在抱怨后者。
要完善这一点,请确保遵循三个规则
这可以很容易地通过修改现有的构造函数声明来实现://For the default constructor
Atom(int zv=0, double xcart=0, double ycart=0, double zcart=0);
编辑:复制构造函数看起来编译器可以找出它。划掉我刚才说的,加上copy assign
&dctor
.
- 找不到成员对象:没有名为get_event()的成员,也处理多态性和向量
- 迭代时从向量和内存中删除对象
- 如何为模板化对象创建模板向量?VS正在投掷C3203
- 为什么我不能将一个对象push_back到属于另一个类的对象向量中?
- 如何创建从同一类继承的不同对象的向量
- 在nlohmann json中,如何将嵌套对象的数组转换为嵌套结构的向量
- 从多个源构造一个对象,包括一个对象向量
- 在C 中,是否有可能在不兼容类型的std ::向量对象之间传输不同类型的缓冲区
- 将向量对象存储在共享指针投掷错误中
- E0312,C2664尝试将向量对象作为函数参数传递时错误
- 相对于向量对象的两个成员,找到两个向量的相交的有效方法
- 将数据从文件读取到向量对象
- C 向量对象访问
- 向量对象声明后的括号是什么意思
- 2向量对象指向相同的分配内存
- 如何返回向量对象
- 传递单个或向量对象时没有重载函数的实例
- 指向数组和向量对象的指针
- 向量对象库,可以存储其他对象类型的对象
- 如何从另一个向量/对象集构造新的向量/指针集