当我尝试编译我编写的这段代码时,我遇到了一些非常令人困惑的编译错误。想法是创建一个对象“分子”,它具有“原子”类型的向量。从包含原子的x,y,z坐标及其Z值的文件中读取每个原子。这是我的代码示例。我已将我的错误追溯到向量,因此我将在下面显示与之关联的所有代码。该程序有点大,它在没有Atom类之前工作(我实现了原子向量来替换在分子类中保持几何的嵌套数组,我试图学习如何使用向量)。
我将矢量初始化为分子类的私有成员,名称为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);
然后继续读取同一个文件,在文件的每一行向向量添加一个原子。
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();
我的向量声明或填充方式是否有问题。如果向量不是我编译错误的来源,我可以发布更多代码,但这是我改变的唯一一方。
如要求Atom类: 头文件:
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::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; }
答案 0 :(得分:6)
编译器正在Atom
类中查找默认构造函数,但它没有默认构造函数。需要默认构造函数的原因是因为这一行:
atoms.resize (natom);
如果新大小大于当前大小, resize()
会向向量添加新元素,并且这些新元素是默认构造的。
你真正想要的是reserve()
:
atoms.reserve (natom);
它只是为存储元素分配内存,但实际上并没有添加任何元素。如果您使用resize()
,则最终会在输入文件中添加两次两个原子 - 一半是默认构造的,与文件数据无关,另一半是值 - 从文件数据构建。
或者,只需完全删除resize()
/ reserve()
,然后在需要时让push_back()
重新分配矢量。但由于您事先知道添加了多少原子,reserve()
是一件好事,因为向量只需要分配一次(除非您在加载文件后添加更多原子)。
答案 1 :(得分:0)
您显然已经解决了您发现的问题。现在让我帮你解决一个你还没有意识到的问题。
我发现你当前的设计存在两个相当严重的问题。首先,你的Molecule类对Atom类的内部细节了解得太多(特别是如何从文件中读取Atom数据)。其次,你的分子类是从它的ctor中的文件中读取分子,但是从文件读取数据应该真正发生在流提取器中。
我的结构更像这样:
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类仅处理Atoms读取大量原子读取的程度,然后读取那么多原子。
至于你如何使用它,你会读到一个类似的分子:
std::ifstream in("Molecule.txt");
Molecule m;
in >> m;
关于它正在做什么以及为什么:Molecule的提取操作符(operator>>
)从文件中提取分子的数据。它通过读取计数,然后从文件中读取该数量的原子来实现。 Atom的提取操作符只是从文件中提取一个Atom的数据,然后返回。
在这两种情况下,它们都遵循返回对istream本身的引用的标准约定,因此调用代码可以在调用后检查流的状态,或者将任意数量的提取串起来,如file >> a >> b >> c;
答案 2 :(得分:-2)
根据cplusplus.com,向量包含项目的副本。您需要声明一个公共拷贝构造函数来允许它,并且需要一个默认构造函数来允许内存分配。看起来它正在抱怨后者。
要解决此问题,make sure to follow the Rule Of Three
通过将现有构造函数声明更改为以下内容,可以轻松完成此操作:
//For the default constructor
Atom(int zv=0, double xcart=0, double ycart=0, double zcart=0);
编辑:复制构造函数看起来像编译器可以解决它。抓一下我对此的评论并添加copy assign
&amp; dctor
。