如何在对象中正确使用整数和浮点数?
How do I use integers and floats within an object correctly?
所以我正在尝试编写一个程序来跟踪具有以下属性的酿酒厂的各种属性。
-动态分配内存
-记录酒厂开始年份的整数
-成功评级和葡萄园占用土地的浮点数。
-添加、删除、显示(按评级和按名称)和保存酒厂数据的功能。
我已经 written/debugged 编写代码来处理所有属性都是 cstring 的类似程序,并且此代码基于相同的框架。
我的问题是,适用于动态分配的 cstring 的相同代码不适用于整数或浮点数,而且我从编译器收到转换错误消息。我有一个包含 aWinery
的 list
class,因为我使用私有成员来隐藏数据,所以我具有从客户端程序传递到 list
和传递到 list
的函数aWinery
。具有相同类型的函数是相同的,所以我在这里只包含每个类型的一个。
有人可以指出我做错了什么吗?如果 aWinery
对 int 和浮点数的定义不是指针,我不知道如何 return 通过参数。我能在 classes 中找到的唯一动态内存编程示例使用 cstrings。我在从讲师那里复制的代码中注意到了几个要点,因为我无法理解。
编辑:我遇到的具体错误是 invalid conversion from int* to int\n year = this->year
,在所有 aWinery
的基于整数和浮点数的访问器和增变器函数中都发生了一些排列。
列出访问器、修改器、构造器和析构器函数
void list::getWineryLocation(char location[]) const
{
wineryData.getLocation(location);
}
void list::getWineryYear(int year) const
{
wineryData.getYear(year);
}
void list::getWineryAcres(float acres) const
{
wineryData.getAcres(acres);
}
void list::setWineryLocation(char location[])
{
wineryData.setLocation(location);
}
void list::setWineryYear(int year)
{
wineryData.setYear(year);
}
void list::setWineryAcres(float acres)
{
wineryData.setAcres(acres);
}
//Constructor functions
list::list()
{
nameHead = NULL;
nameTail = NULL;
ratingHead = NULL;
ratingTail = NULL;
size = 0;
}
//Destructor
//Doesn't delete the head/tailRating pointers to avoid double deleting a winery
list::~list()
{
node * curr = nameHead;
while (nameHead != NULL)
{
curr = nameHead->nextByName;
delete nameHead;
nameHead = curr;
}
}
aWinery Accessor、Mutator、Constructor 和 Destructor 函数
//Winery object constructor
aWinery::aWinery()
{
name = new char[strlen("Unknown")+1];
strcpy(name, "Unknown");
location = new char[strlen("Unknown")+1];
strcpy(location, "Unknown");
year = new int;
year = 0;
acres = new float;
acres = 0;
successRating = new float;
successRating = 0;
}
//I have no idea whats going on here
//Winery destructor
aWinery::~aWinery()
{
if(name != NULL)
delete [] name;
if(location != NULL)
delete [] location;
if(year != 0)
delete year;
if(acres != 0)
delete acres;
if(successRating != 0)
delete successRating;
}
void aWinery::getLocation(char location[]) const
{
strcpy(location, this->location);
}
void aWinery::getYear(int year) const
{
year = this->year;
}
void aWinery::getAcres(float acres) const
{
acres = this->acres;
}
//I have no idea why this is written this way, I copied this from an instructor example
void aWinery::setLocation(char location0[])
{
if(this->location != NULL)
delete [] this->location;
this->location = new char[strlen(location0)+1];
strcpy(this->location, location0);
}
void aWinery::setYear(int year0)
{
if(this->year != 0)
delete this->year;
this->year = new int;
this->year = year0;
}
void aWinery::setAcres(float acres0)
{
if(this->acres != 0)
delete this->acres;
this->acres = new float;
this->acres = acres0;
}
一个酒厂头文件
#ifndef AWINERY_H
#define AWINERY_H
#include <iostream>
using namespace std;
//winery object
class aWinery
{
public:
//Constructor
aWinery();
//Destructor
~aWinery();
//Accessor Prototypes
void getName(char name[]) const;
void getLocation(char location[]) const;
void getYear(int year) const;
void getAcres(float acres) const;
void getSuccessRating(float successRating) const;
//Mutator Prototypes
void setName(char name0[]);
void setLocation(char location0[]);
void setYear(int year0);
void setAcres(float acres0);
void setSuccessRating(float successRating0);
private:
char* name;
char* location;
int* year;
float* acres;
float* successRating;
};
#endif
列出头文件
#ifndef ALIST_H
#define ALIST_H
#include <iostream>
using namespace std;
const int MAX_CHAR_LENGTH = 1000;
class list
{
public:
//Prototypes
void setInWinery(char name[], char location[], int year, float acres, float successRating);
void initializeDbase(char savePathName[]);
void printEntireDbase();
void deleteWinery(char nameOfWinery[]);
void whereIsWinery(char nameOfWinery[]);
void save(char savePathName[]);
//Accessor Prototypes
void getWineryName(char name[]) const;
void getWineryLocation(char location[]) const;
void getWineryYear(int year) const;
void getWineryAcres(float acres) const;
void getWinerySuccessRating(float successRating) const;
int getSize() const;
//Mutator Prototypes
void setWineryName(char name[]);
void setWineryLocation(char location[]);
void setWineryYear(int year);
void setWineryAcres(float acres);
void setWinerySuccessRating(float successRating);
//Constructor Prototype
list();
//Destructor
~list();
private:
//Wine object
struct node
{
aWinery wineryData;
node * nextByName;
node * nextByRating;
};
node * nameHead, * nameTail, * ratingHead, * ratingTail;
aWinery wineryData;
int size;
};
#endif
我认为您的大部分问题出在 header,此处:
private:
char* name;
char* location;
int* year;
float* acres;
float* successRating;
真的没有理由为这些成员变量中的任何一个使用指针;你不妨让他们都成为 plain-old by-value 成员,像这样:
private:
std::string name;
std::string location;
int year;
float acres;
float successRating;
请注意,我将 (char *) 成员变量替换为 std::string,因为在 C++ 程序中确实没有理由不使用适当的字符串 object。 (如果你用 C 编写,使用动态分配的 char 数组来保存字符串可能是一个必要的邪恶,但在 C++ 中它只是受虐狂)
通过存储所有数据 by-value,您可以摆脱所有 new
和 delete
命令(以及随之而来的不可避免的错误和低效率)和必要时直接设置和获取值即可。
另外,这个存取函数是错误的:
void aWinery::getYear(int year) const
{
year = this->year;
}
它不会工作,因为在 C++ 中,方法参数(默认情况下)按值传递(即制作 passed-in 值的临时本地副本,供方法使用),所以所有上面的方法就是修改局部参数year
,然后在函数returns时立即销毁。一个合适的访问器方法看起来更像这样:
int aWinery::getYear() const
{
return this->year; // assuming year member variable is now of type int
}
..... 同样,setter 方法应该如下所示:
void aWinery::setYear(int newYear)
{
this->year = newYear; // assuming year member variable is now of type int
}
所以我正在尝试编写一个程序来跟踪具有以下属性的酿酒厂的各种属性。
-动态分配内存
-记录酒厂开始年份的整数
-成功评级和葡萄园占用土地的浮点数。
-添加、删除、显示(按评级和按名称)和保存酒厂数据的功能。
我已经 written/debugged 编写代码来处理所有属性都是 cstring 的类似程序,并且此代码基于相同的框架。
我的问题是,适用于动态分配的 cstring 的相同代码不适用于整数或浮点数,而且我从编译器收到转换错误消息。我有一个包含 aWinery
的 list
class,因为我使用私有成员来隐藏数据,所以我具有从客户端程序传递到 list
和传递到 list
的函数aWinery
。具有相同类型的函数是相同的,所以我在这里只包含每个类型的一个。
有人可以指出我做错了什么吗?如果 aWinery
对 int 和浮点数的定义不是指针,我不知道如何 return 通过参数。我能在 classes 中找到的唯一动态内存编程示例使用 cstrings。我在从讲师那里复制的代码中注意到了几个要点,因为我无法理解。
编辑:我遇到的具体错误是 invalid conversion from int* to int\n year = this->year
,在所有 aWinery
的基于整数和浮点数的访问器和增变器函数中都发生了一些排列。
列出访问器、修改器、构造器和析构器函数
void list::getWineryLocation(char location[]) const
{
wineryData.getLocation(location);
}
void list::getWineryYear(int year) const
{
wineryData.getYear(year);
}
void list::getWineryAcres(float acres) const
{
wineryData.getAcres(acres);
}
void list::setWineryLocation(char location[])
{
wineryData.setLocation(location);
}
void list::setWineryYear(int year)
{
wineryData.setYear(year);
}
void list::setWineryAcres(float acres)
{
wineryData.setAcres(acres);
}
//Constructor functions
list::list()
{
nameHead = NULL;
nameTail = NULL;
ratingHead = NULL;
ratingTail = NULL;
size = 0;
}
//Destructor
//Doesn't delete the head/tailRating pointers to avoid double deleting a winery
list::~list()
{
node * curr = nameHead;
while (nameHead != NULL)
{
curr = nameHead->nextByName;
delete nameHead;
nameHead = curr;
}
}
aWinery Accessor、Mutator、Constructor 和 Destructor 函数
//Winery object constructor
aWinery::aWinery()
{
name = new char[strlen("Unknown")+1];
strcpy(name, "Unknown");
location = new char[strlen("Unknown")+1];
strcpy(location, "Unknown");
year = new int;
year = 0;
acres = new float;
acres = 0;
successRating = new float;
successRating = 0;
}
//I have no idea whats going on here
//Winery destructor
aWinery::~aWinery()
{
if(name != NULL)
delete [] name;
if(location != NULL)
delete [] location;
if(year != 0)
delete year;
if(acres != 0)
delete acres;
if(successRating != 0)
delete successRating;
}
void aWinery::getLocation(char location[]) const
{
strcpy(location, this->location);
}
void aWinery::getYear(int year) const
{
year = this->year;
}
void aWinery::getAcres(float acres) const
{
acres = this->acres;
}
//I have no idea why this is written this way, I copied this from an instructor example
void aWinery::setLocation(char location0[])
{
if(this->location != NULL)
delete [] this->location;
this->location = new char[strlen(location0)+1];
strcpy(this->location, location0);
}
void aWinery::setYear(int year0)
{
if(this->year != 0)
delete this->year;
this->year = new int;
this->year = year0;
}
void aWinery::setAcres(float acres0)
{
if(this->acres != 0)
delete this->acres;
this->acres = new float;
this->acres = acres0;
}
一个酒厂头文件
#ifndef AWINERY_H
#define AWINERY_H
#include <iostream>
using namespace std;
//winery object
class aWinery
{
public:
//Constructor
aWinery();
//Destructor
~aWinery();
//Accessor Prototypes
void getName(char name[]) const;
void getLocation(char location[]) const;
void getYear(int year) const;
void getAcres(float acres) const;
void getSuccessRating(float successRating) const;
//Mutator Prototypes
void setName(char name0[]);
void setLocation(char location0[]);
void setYear(int year0);
void setAcres(float acres0);
void setSuccessRating(float successRating0);
private:
char* name;
char* location;
int* year;
float* acres;
float* successRating;
};
#endif
列出头文件
#ifndef ALIST_H
#define ALIST_H
#include <iostream>
using namespace std;
const int MAX_CHAR_LENGTH = 1000;
class list
{
public:
//Prototypes
void setInWinery(char name[], char location[], int year, float acres, float successRating);
void initializeDbase(char savePathName[]);
void printEntireDbase();
void deleteWinery(char nameOfWinery[]);
void whereIsWinery(char nameOfWinery[]);
void save(char savePathName[]);
//Accessor Prototypes
void getWineryName(char name[]) const;
void getWineryLocation(char location[]) const;
void getWineryYear(int year) const;
void getWineryAcres(float acres) const;
void getWinerySuccessRating(float successRating) const;
int getSize() const;
//Mutator Prototypes
void setWineryName(char name[]);
void setWineryLocation(char location[]);
void setWineryYear(int year);
void setWineryAcres(float acres);
void setWinerySuccessRating(float successRating);
//Constructor Prototype
list();
//Destructor
~list();
private:
//Wine object
struct node
{
aWinery wineryData;
node * nextByName;
node * nextByRating;
};
node * nameHead, * nameTail, * ratingHead, * ratingTail;
aWinery wineryData;
int size;
};
#endif
我认为您的大部分问题出在 header,此处:
private:
char* name;
char* location;
int* year;
float* acres;
float* successRating;
真的没有理由为这些成员变量中的任何一个使用指针;你不妨让他们都成为 plain-old by-value 成员,像这样:
private:
std::string name;
std::string location;
int year;
float acres;
float successRating;
请注意,我将 (char *) 成员变量替换为 std::string,因为在 C++ 程序中确实没有理由不使用适当的字符串 object。 (如果你用 C 编写,使用动态分配的 char 数组来保存字符串可能是一个必要的邪恶,但在 C++ 中它只是受虐狂)
通过存储所有数据 by-value,您可以摆脱所有 new
和 delete
命令(以及随之而来的不可避免的错误和低效率)和必要时直接设置和获取值即可。
另外,这个存取函数是错误的:
void aWinery::getYear(int year) const
{
year = this->year;
}
它不会工作,因为在 C++ 中,方法参数(默认情况下)按值传递(即制作 passed-in 值的临时本地副本,供方法使用),所以所有上面的方法就是修改局部参数year
,然后在函数returns时立即销毁。一个合适的访问器方法看起来更像这样:
int aWinery::getYear() const
{
return this->year; // assuming year member variable is now of type int
}
..... 同样,setter 方法应该如下所示:
void aWinery::setYear(int newYear)
{
this->year = newYear; // assuming year member variable is now of type int
}