这个类的C++声明有什么问题?
我的教授给了我们这门课,并告诉我们它不会编译。他表示捐助者阵列会与构造者发生冲突。所以...为什么会这样呢?这个类的C++声明有什么问题?
我认为Donor
阵列的名称可能做到这一点,但由于成员数组donor
的名称是区分大小写,因此比类名不同,应该不是问题。
下面的代码:
#ifndef DONORS_H
#define DONORS_H
#include <string>
#include "name.h"
#include "donor.h"
using namespace std;
const int
DONORS_LOAD_ERROR = 1,
DONORS_UPDATE_ERROR = 2,
DONORS_ADD_ERROR = 3;
const int MAX_DONORS = 100;
class Donors {
public:
Donors() : size(0) {}
void load(string filename);
int getSize() {return size;}
int find(Name name);
int add(Name name);
int add(Name name, Donation donation, int ytd);
void processDonation(Name name, Donation donation);
void update(string filename);
void print();
private:
Donor donorsList[MAX_DONORS];
int size;
};
#endif
教授写道:
在这个版本中,我们已经采取了第2版,添加构造函数,并最大限度地利用对象。
然而,引入构造函数会破坏Donors类中数组数据成员的声明; 因此这个版本不编译!
我一直在和同学讨论这件事,我们都很难过。这个C++类是什么?
编辑:
编译器的消息如下:
它只是发生在我身上的捐赠类有一个构造函数。因为我们没有触及十脚的矢量,我们究竟应该怎样编译这个?
EDIT2:
这里的施主类:
#ifndef DONOR_H
#define DONOR_H
#include "name.h"
#include "donation.h"
using namespace std;
class Donor {
public:
Donor(Name n, Donation ld=Donation(0, 0), int y=0) : name(n), lastDonation(ld), ytd(y) {}
Name getName() {return name;}
Donation getLastDonation() {return lastDonation;}
int getYtd() {return ytd;}
void processDonation(Donation d);
private:
Name name;
Donation lastDonation;
int ytd;
};
#endif
难而不Donor
类的定义说,但我的猜测是,他增加了一个构造函数参数的Donor
类,所以它不会再有隐式的默认构造函数。
但是现在,没有默认构造函数,这是一个可以不带参数调用的构造函数,因此无法声明这种类型的数组,因为没有办法传递所需的参数!
您的预感是正确的:http://chat.*.com/transcript/message/2990667#2990667。 – sbi 2012-03-19 17:26:47
我的猜测是类Donor
(你没有包括)没有默认的构造函数。如果是的话,你会得到一个编译错误,因为这条线:
Donor donorsList[MAX_DONORS];
将尝试使用构造与 - 无参数Donor
没有。
如果您遇到您的导师向您展示的错误,它将帮助您在课程中做得更好。那么当你在现实生活中遇到他们时,你会认出他们。如果你要学习C++,那么“我和朋友看着这个并且应该编译好”的策略永远不会成为尝试编译它并查看你得到什么错误的替代品。
你的预感是正确的:http://chat.*.com/transcript/message/2990667#2990667。 – sbi 2012-03-19 17:25:59
您需要包含class Donor
的定义。
从外观上看,我猜class Donor
有一个非默认构造函数,即i。即构造函数接受一个或多个参数。在这种情况下,编译器不会生成class Donor
的默认构造函数,您必须自己定义它。
创建donorsList
需要默认构造函数,因为当您创建一个对象数组时,将为每个对象调用默认的构造函数。
首先考虑Donors
类:
#ifndef DONORS_H
#define DONORS_H
#include <string>
#include "name.h"
#include "donor.h"
OK为止。
using namespace std;
不!永远不要将using namespace std;
放在标题中的全局名称空间中。作者(你的教授)几乎可以保证愚蠢的名字冲突,比如编译器在一些不好的用户’的代码中抱怨distance
。
const int
DONORS_LOAD_ERROR = 1,
DONORS_UPDATE_ERROR = 2,
DONORS_ADD_ERROR = 3;
const int MAX_DONORS = 100;
这些都是坏名字。保留呼吁所有大写的宏名称。但是,请将它们用于宏名称。
此外,最好使用enum
这样的常数。
此外,还可以更好地使用异常来进行故障报告。
class Donors {
public:
Donors() : size(0) {}
void load(string filename);
的string
参数会更好通过引用传递给const
。
int getSize() {return size;}
该方法应该是const
。
此外,虽然前缀get
在一些语言如Java和C#,支持instrospection(因此基于内省工具)的实际优势,在C++中,它只是愚蠢的冗长–在大多数情况下,在这种情况下。
更好地调用该方法只需name
。
准则:考虑调用代码的可读性。
int find(Name name);
的name
说法可能会更好,因为参考const
传递。
int add(Name name);
的name
说法可能会更好,因为参考const
传递。
int add(Name name, Donation donation, int ytd);
的name
和donation
参数可能会更好,因为到const
引用传递。
名称ytd
非常糟糕。猜测它的含义是非常困难的。
void processDonation(Name name, Donation donation);
的name
和donation
参数可能会更好,因为到const
引用传递。
界面不明确:add
和process
有什么区别?
void update(string filename);
的name
说法可能会更好,因为参考const
传递。
这种方法的名称很糟糕。
几乎不可能猜到这个方法做了什么。
void print();
这个方法究竟应该在哪里打印什么,以什么格式?
private:
Donor donorsList[MAX_DONORS];
这个声明要求Donor
有一个构造函数可以不带参数调用,一个默认构造函数。
int size;
};
#endif
考虑到第二Donor
类:
#ifndef DONOR_H
#define DONOR_H
#include "name.h"
#include "donation.h"
OK为止。
using namespace std;
不!永远不要将using namespace std;
放在标题中的全局名称空间中。作者(你的教授)几乎可以保证愚蠢的名字冲突,比如编译器在一些不好的用户’的代码中抱怨distance
。
class Donor {
public:
Donor(Name n, Donation ld=Donation(0, 0), int y=0) : name(n), lastDonation(ld), ytd(y) {}
y
和ytd
是坏的名字。现在不可能猜到他们’是关于什么的。
ld
是个不好的名字。
Name
和Donation
参数应该可能更好地通过参考const
来传递。
注意:当有一个用户声明的构造函数,比如上面的那个,那么默认的构造函数不会自动生成。
Name getName() {return name;}
该方法应该是const
。
此外,虽然前缀get
在一些语言如Java和C#,支持instrospection(因此基于内省工具)的实际优势,在C++中,它只是愚蠢的冗长–在大多数情况下,在这种情况下。
更好地调用该方法只需name
。
准则:考虑调用代码的可读性。
Donation getLastDonation() {return lastDonation;}
请参阅上面的注释。
int getYtd() {return ytd;}
请参阅上面的注释。
void processDonation(Donation d);
该参数应该最好通过参考const
来传递。
private:
Name name;
Donation lastDonation;
int ytd;
};
#endif
总之,Donors
类需要Donor
有一个默认的构造函数,但由于Donor
具有不产生默认构造方法的用户声明的构造。
一种修复方法是用std::vector
或其他集合取代简单阵列,例如,
std::vector<Donor> donors_;
或
std::map< std::string, Donor > donors_;
'捐助者'是我认为'捐赠者'对象的容器。 – 2012-03-19 18:21:20
呵呵,名字的细微差别。我没有看到。让我解决答案。 OK完成。 – 2012-03-19 18:32:34
“不会编译” 是不够的错误描述,你知道的。 – Griwes 2012-03-19 17:17:10
当你试图编译它时,你得到了什么错误信息? – 2012-03-19 17:17:32
编译错误是什么? – octal9 2012-03-19 17:17:39