我的代码:
class item{
int plu;
char * name;
double price;
double inv;
public:
void setPLU(int g) { plu = g; }
void setName(const char * p) { name = copyStr(p); }
void setPrice(double g) { price = g; }
void setInventory(double g) { inv = g; }
int getPlu() { return plu; }
char*getName() { return name; }
double getPrice() { return price; }
double getInventory() { return inv; }
item(){
name = nullptr;
}
~item(){
delete name;
}
};
class puItem : public item{
bool type;
public:
void setType(bool g) { type = g; }
bool getType() { return type; }
};
class nodeU{
puItem fruit;
nodeU * next;
public:
nodeU * getNext(){ return next; }
puItem getFruit(){ return fruit; }
void setNext(nodeU * g){ next = g; }
void setFruit(puItem g) { fruit = g; }
nodeU(){
next = nullptr;
}
};
class linkedListU{
nodeU * head;
int size;
public:
nodeU * getHead(){
return head;
}
void setHead(nodeU * n){
head = n;
}
//Append
void appendNode(nodeU * n){
if (head == nullptr){
head = n;
}
else{
nodeU * iter = head;
while (iter){
iter = iter->getNext();
}
iter->setNext(n);
}
size++;
}
linkedListU()
{
head = nullptr;
size = 0;
}
puItem * pluLookup(int g){
nodeU * iter = head;
while (iter)
{
if ((iter->getFruit()).getPlu() == g)
return &(iter->getFruit());
iter = iter->getNext();
}
return nullptr;
}
};
void checkout(linkedListP, linkedListU);
linkedListU unitList;
linkedListP poundList;
nodeU * inputU=new nodeU;
int main()
{
ifstream infile;
ofstream outfile;
int tempPlu;
string tempName;
bool tempType;
double tempPrice, tempInv;
infile.open("products.txt");
puItem unit;
infile >> tempPlu;
if (!infile.good())
{
infile.clear();
infile.ignore();
}
infile >> tempName;
if (!infile.good())
{
infile.clear();
infile.ignore();
}
infile >> tempType;
if (!infile.good())
{
infile.clear();
infile.ignore();
}
infile >> tempPrice;
if (!infile.good())
{
infile.clear();
infile.ignore();
}
infile >> tempInv;
if (!infile.good())
{
infile.clear();
infile.ignore();
}
if (tempType == 0){
unit.setInventory(tempInv);
unit.setName(tempName.c_str());
unit.setPLU(tempPlu);
unit.setType(tempType);
unit.setPrice(tempPrice);
inputU->setFruit(unit);
unitList.appendNode(inputU);
}
checkout(poundList, unitList);
system("pause");
return 0;
}
void checkout(linkedListU p){
int key = -10;
puItem * searchU=nullptr;
int counter = 0;
double total = 0;
double amount;
cout << "Enter the plu for the item you want or enter 0 to exit: ";
cin >> key;
while (key < 0)
{
cout << "\nInvalid input please re enter: ";
cin >> k
searchU = p.pluLookup(key);
}
while (key)
{
当它进入plu查找它会抛出错误,我似乎无法找出原因。 我知道错误是删除了两次但我在这段代码中找不到任何实例。
答案 0 :(得分:1)
您的代码存在很多问题,其中大部分都是由于您的类无法安全复制(它们缺少用户定义的复制构造函数和赋值运算符以及析构函数)。请参阅3的规则:
您的checkout
函数具有以下原型:
void checkout(linkedListU p){
这意味着您按值传递linkedListU
。由于linkedListU
未能遵循3的规则,因此当您按值传递此类型时,将调用编译器定义的复制构造函数,该构造函数仅生成浅拷贝,从而导致未定义的行为。
您的链接列表的成员是指向动态分配内存的指针,需要按照上面链接中的规则3 正确处理它们。由于您没有这样做,因此无法安全地传递值。
要解决此问题,您可以按引用传递链接列表,而不是按值传递:
void checkout(linkedListU& p){
这将停止复制,但它确实没有解决未在任何类中使用的3规则的基本问题。
例如,您的puItem
按puItem::getFruit
函数中的值返回,并且还通过puItem::setFruit
函数中的值传递。在没有任何更改的情况下调用这些函数也会调用未定义的行为,因为这些类不能安全地复制(也是由于您使用了指向动态分配的内存的成员)。
要解决此问题,您可以做的第一件事是将基类item
更改为使用std::string name;
而不是char *name;
。这使得item
现在成为一个可复制的类,无需编写用户定义的复制操作或者需要delete name;
的析构函数。原因是,使用std::string
后,item
中的所有成员都可以在没有用户干预的情况下进行复制。编译器默认版本就足够了。
class item
{
int plu;
std::string name;
double price;
double inv;
public:
void setPLU(int g) { plu = g; }
void setName(const char * p) { name = p; }
void setPrice(double g) { price = g; }
void setInventory(double g) { inv = g; }
int getPlu() { return plu; }
std::string getName() { return name; }
double getPrice() { return price; }
double getInventory() { return inv; }
};
请注意,不需要析构函数。现在,当puItem
派生自此类时,puItem
现在也可以安全地复制,您可以按值传递并返回puItem
:
class puItem : public item
{
bool type;
public:
void setType(bool g) { type = g; }
bool getType() { return type; }
};
进行这些更改完全消除了这些类的使用导致堆错误,双重删除错误或内存泄漏。有关内存问题的任何进一步错误现在都集中在您的链表类(使用动态分配的内存)上。至少,这个问题已经缩小了很多,现在已经成为焦点。