C++ 代码行不';两行之后我就不工作了
这令人困惑。我需要在我的程序中使用一个函数CCountry::getName()。奇怪的是,当测试它是否工作时,它在一个地方工作,但在两行下不工作,我不知道为什么。例如C++ 代码行不';两行之后我就不工作了,c++,list,function,C++,List,Function,这令人困惑。我需要在我的程序中使用一个函数CCountry::getName()。奇怪的是,当测试它是否工作时,它在一个地方工作,但在两行下不工作,我不知道为什么。例如 while(line != "---" && line != "------") { CCountry *tempCountry = new CCountry(line); cout << tempCountry->getName() << f
while(line != "---" && line != "------")
{
CCountry *tempCountry = new CCountry(line);
cout << tempCountry->getName() << flush;
(*tempContinent).addCountry(*tempCountry);
getline(filestr, line);
}
及
根据请求,以下是cccountry构造函数:
CCountry::CCountry(string in_name)
{
name = new string;
*name = in_name;
player = new int;
*player = -1;
units = new int;
*units = 0;
neighbors = new list<CCountry>;
}
CCountry::CCountry(名称中的字符串)
{
name=新字符串;
*姓名=姓名;
玩家=新整数;
*玩家=-1;
单位=新整数;
*单位=0;
邻居=新列表;
}
您是否可能在CCountry的构造函数中造成某种覆盖?听起来很像。我可以用这段代码列出一长串错误,但导致您出错的原因最终是以下原因:
您的CCountry类没有练习,它必须练习,因为它有动态分配的成员。(顺便说一句,甚至不需要)
您正在通过一个成员函数将Accounty对象添加到您的大陆,该函数按值获取国家。此时将制作对象的浅拷贝。然后将其推入大陆内的容器中,从而生成另一个浅拷贝。在addCountry()退出时,原始的浅层副本将被销毁,在这个过程中,当您返回到调用代码时,CCCountry对象的内部已被销毁。因此,您的本地(不应该在第一个位置动态分配,顺便说一句)是正式的软管
猜猜看。。。你们大陆集装箱里的那个也是
我可能会首先考虑CCountry对象本身。就我个人而言,我会在CContinent类而不是CCountry中管理CCountry的邻居,因为这是管理CCountry对象集合的地方,但每个对象都有自己的邻居。如果您决定坚持使用当前模型,那么CCountry的一个潜在替代方案可能是:
class CCountry
{
public:
CCountry(const std::string& name)
: name(name), player(0), units(0)
{
}
// properties
const std::string& getName() const { return name; };
int getPlayer() const { return player; };
void setPlayer(int player) { this->player = player; };
int getUnits() const { return units; };
void setUnits(int units) { this->units = units; };
// neighbor access
const std::list<const CCountry*> getNeighbors() const
{
std::list<const CCountry*> res;
for (auto it=neighbors.begin(); it != neighbors.end(); ++it)
res.push_back(it->second);
return res;
}
// adding a new neighbor
void addNeighbor(const CCountry& other)
{
neighbors[ other.getName() ] = &other;
}
private:
std::string name;
int player;
int units;
std::map<std::string, const CCountry*> neighbors;
};
~CCountry() {
delete name;
delete player;
delete units;
delete neighbors;
}
CCountry(CCountry const &that) :
name(that.name),
player(that.player),
units(that.units),
neighbors(that.neightbors)
{ }
class CCountry {
string name;
int player;
int units;
list<CCountry *> neighbors;
};
类国家
{
公众:
CCountry(常量标准::字符串和名称)
:姓名(姓名)、玩家(0)、单位(0)
{
}
//性质
const std::string&getName()const{return name;};
int getPlayer()常量{return player;};
void setPlayer(int player){this->player=player;};
int getUnits()常量{return units;};
void setUnits(整数单位){this->units=units;};
//邻居访问
常量std::list getneights()常量
{
std::list res;
for(auto it=neights.begin();it!=neights.end();+it)
res.push_back(它->秒);
返回res;
}
//添加新邻居
无效添加邻居(施工国家和其他)
{
邻居[other.getName()]=&other;
}
私人:
std::字符串名;
国际球员;
整数单位;
地图邻居;
};
但请注意:采用这样的模型(正如您所看到的,您的原始模型)会有潜在的缺陷,特别是一个国家可能有指向另一个技术上不属于它的国家的指针。这就是为什么我希望邻居关联由CContinent类本身管理,因为它同时拥有CCountry及其邻居关联。我怀疑您定义了一个类似于以下内容的
CCountry
析构函数:
class CCountry
{
public:
CCountry(const std::string& name)
: name(name), player(0), units(0)
{
}
// properties
const std::string& getName() const { return name; };
int getPlayer() const { return player; };
void setPlayer(int player) { this->player = player; };
int getUnits() const { return units; };
void setUnits(int units) { this->units = units; };
// neighbor access
const std::list<const CCountry*> getNeighbors() const
{
std::list<const CCountry*> res;
for (auto it=neighbors.begin(); it != neighbors.end(); ++it)
res.push_back(it->second);
return res;
}
// adding a new neighbor
void addNeighbor(const CCountry& other)
{
neighbors[ other.getName() ] = &other;
}
private:
std::string name;
int player;
int units;
std::map<std::string, const CCountry*> neighbors;
};
~CCountry() {
delete name;
delete player;
delete units;
delete neighbors;
}
CCountry(CCountry const &that) :
name(that.name),
player(that.player),
units(that.units),
neighbors(that.neightbors)
{ }
class CCountry {
string name;
int player;
int units;
list<CCountry *> neighbors;
};
但我怀疑您没有为CCountry
定义副本构造函数。这意味着编译器正在生成一个副本构造函数,如下所示:
class CCountry
{
public:
CCountry(const std::string& name)
: name(name), player(0), units(0)
{
}
// properties
const std::string& getName() const { return name; };
int getPlayer() const { return player; };
void setPlayer(int player) { this->player = player; };
int getUnits() const { return units; };
void setUnits(int units) { this->units = units; };
// neighbor access
const std::list<const CCountry*> getNeighbors() const
{
std::list<const CCountry*> res;
for (auto it=neighbors.begin(); it != neighbors.end(); ++it)
res.push_back(it->second);
return res;
}
// adding a new neighbor
void addNeighbor(const CCountry& other)
{
neighbors[ other.getName() ] = &other;
}
private:
std::string name;
int player;
int units;
std::map<std::string, const CCountry*> neighbors;
};
~CCountry() {
delete name;
delete player;
delete units;
delete neighbors;
}
CCountry(CCountry const &that) :
name(that.name),
player(that.player),
units(that.units),
neighbors(that.neightbors)
{ }
class CCountry {
string name;
int player;
int units;
list<CCountry *> neighbors;
};
现在,CContinent::addCountry
被定义为接受CCountry
,而不是CCountry&
。因此,当您执行(*tempCountry).addCountry(*tempCountry)
时,您的程序会使用编译器定义的CCountry
复制构造函数来生成*tempCountry
的(临时)副本
因此,现在您的程序有两个独立的CCountry
实例:一个由tempCountry
指向,另一个在CContinent::addCountry
的country
参数中。但是由于编译器定义的复制构造函数的工作方式,两个实例都有name
成员变量指向同一string
实例
删除临时副本时,其析构函数将删除该字符串实例。现在,tempCountry
指向的实例在其name
成员变量中有一个悬空指针。当您尝试取消引用getName
中的悬空指针时,该行为未定义,并导致分段错误
将您的名称
、播放器
、单位
和邻居
成员变量更改为非指针。它们应该是普通类型,如下所示:
class CCountry
{
public:
CCountry(const std::string& name)
: name(name), player(0), units(0)
{
}
// properties
const std::string& getName() const { return name; };
int getPlayer() const { return player; };
void setPlayer(int player) { this->player = player; };
int getUnits() const { return units; };
void setUnits(int units) { this->units = units; };
// neighbor access
const std::list<const CCountry*> getNeighbors() const
{
std::list<const CCountry*> res;
for (auto it=neighbors.begin(); it != neighbors.end(); ++it)
res.push_back(it->second);
return res;
}
// adding a new neighbor
void addNeighbor(const CCountry& other)
{
neighbors[ other.getName() ] = &other;
}
private:
std::string name;
int player;
int units;
std::map<std::string, const CCountry*> neighbors;
};
~CCountry() {
delete name;
delete player;
delete units;
delete neighbors;
}
CCountry(CCountry const &that) :
name(that.name),
player(that.player),
units(that.units),
neighbors(that.neightbors)
{ }
class CCountry {
string name;
int player;
int units;
list<CCountry *> neighbors;
};
类国家{
字符串名;
国际球员;
整数单位;
列出邻居;
};
您可能还希望更改函数以获取引用而不是副本。在您的国家/地区的构造函数中,您使用
新字符串分配名称,在析构函数中,您可能使用删除名称来释放名称。我不知道您为什么需要这样做,将string
存储为CCountry
的name
成员可能更简单。当您将CCountry
作为参数传递给CContinent::addCountry
时,将创建并删除它的临时副本,这将导致删除在CCountry
的多个实例之间共享的CCountry::name
。为了避免这种情况,您需要使用string
而不是string*
作为CCountry
的成员name
,或者实现您自己的CCountry复制构造函数。此代码存在许多问题,但对于初学者来说,
CCountry
是否具有值语义,或者它是实体类型。
在第一种情况下,不应该有指向它的指针,或者
使用new
动态分配它。你应该确保
它可以被正确地复制和使用