我需要检查我的对象Course
是否处于安全空状态。
这是我失败的尝试:
const bool Course::isEmpty() const {
if (Course() == nullptr) {
return true;
}
else {
return false;
}
}
构造
Course::Course() {
courseTitle_ = new char[21]; // name
courseTitle_ = '\0';
credits_ = 0;//qtyNeeded
studyLoad_ = 0;//quantity
strcpy(courseCode_, "");//sku
}
Course::Course(const char* courseCode, const char* courseTitle, int credits , int studyLoad ) {
strcpy(courseCode_, courseCode);
courseTitle_ = new char[21];
strcpy(courseTitle_, courseTitle);
studyLoad_ = studyLoad;
credits_ = credits;
}
显然,执行course()== nullptr并不是真正检查对象是否处于安全空状态,如果设置为0则检查单个变量将无法在我的程序中运行。我需要检查整个对象是否设置为安全的空状态。
编辑:有些人问我的empty()函数假设使用了什么。有一个测试人员可以测试我的isEmpty()是否运行良好。
bool isEmptyTest0() {
// empty test
sict::Course c0;
return c0.isEmpty();
}
bool isEmptyTest1() {
// empty test
sict::Course c0("", "title", 3, 3);
return c0.isEmpty();
}
bool isEmptyTest2() {
// empty test
sict::Course c0("code", "", 3, 3);
return c0.isEmpty();
}
bool isEmptyTest3() {
// empty test
sict::Course c0("code", "title", -1, 3);
return c0.isEmpty();
}
bool isEmptyTest4() {
// empty test
sict::Course c0("code", "title", 3, -1);
return c0.isEmpty();
}
bool regularInitTest() {
// regular
sict::Course c5("OOP244", "Object-Oriented Programming in C++", 1, 4);
return (!c5.isEmpty()
&& !strcmp("OOP244", c5.getCourseCode())
&& !strcmp("Object-Oriented Programming in C++", c5.getCourseTitle())
&& (c5.getCredits() == 1)
&& c5.getStudyLoad() == 4
);
}
请注意,在regularInitTest()
中,我的赋值运算符运行正常,但它永远不会传递!c5.isEmpty()
,因为它失败了。希望我能正确解释。
答案 0 :(得分:0)
这里最常见的就是你应该做些什么来让测试通过。
在第二个(4参数)构造函数中,对输入进行一些检查,例如检查void calculate(const float *payperhour, const float *hoursworked, float *wage, float *overtime, int p) {
if (hoursworked[p] > 40) {
overtime[p] = ((hoursworked[p] - 40) * payperhour[p] * 1.5);
wage[p] = overtime[p] + (payperhour[p] * 40);
} else {
overtime[p] = 0;
wage[p] = hoursworked[p] * payperhour[p];
}
}
是否为正数。检查所有可能出现的错误的所有参数,包括isEmptyTest0..4中的错误。如果有错误,则以与1st(0-argument)构造函数相同的方式初始化对象。如果没有错误,请从参数初始化数据成员。
以下是如何实现credits
方法:如果对象的所有数据成员都具有空/零/默认值,则应返回true,如第1(0参数)构造函数初始化。 / p>
概念安全空状态本身仍然没有意义,但教授试图教导的概念确实有意义。我会在这里总结一下我的理解。构造函数可以接收无效的参数,根据这些参数,它无法初始化有意义且有效的对象。程序员应该在程序的各处添加用于错误检查和处理的代码,包括构造函数。在构造函数中有多种方法可以进行输入验证和错误处理,例如:抛出异常2.使用错误消息中止整个程序; 3.将对象初始化为特殊的无效状态; 4.将对象初始化为特殊的空状态。 (这也是一种选择,但强烈建议不要推荐:5。保持对象的一些数据成员未初始化。)这些方法中的每一种都有利有弊。在这项任务中,教授希望你实施#4。请参阅我的答案中的第2段如何操作。
当教授要求安全空状态时,他很可能意味着你应该在构造函数中进行输入验证,并且如果在#4而不是#5时出错。< / p>
答案 1 :(得分:0)
我同意pts 安全空状态定义不明确。
在阅读评论后,在我看来,缺少的原则是资源获取是初始化(RAII)。构造函数是一种事务,在某种程度上:你得到
有效这里是由类定义的。通常,这意味着传递的参数被合并到对象中,并且成功分配和/或找到了所有必需的资源。
中止程序很少是一个选项,并且从构造函数返回错误永远不会。构造无效对象通常仅在禁止例外的环境中进行。
有一种特殊情况:默认构造函数。有时需要“做空”的东西,以后会完全初始化。
考虑std::string
。它可以用值构造,如果无法分配内存则抛出异常。或者它可以在没有值的情况下构建,稍后分配一个。你的类可能类似,在这种情况下,安全空只是意味着用户在调用“init”函数时会很乐意销毁的状态。您不必测试每个成员变量;你只需要检查一些只对完全初始化的对象才真实的东西。
然后就是“有效”的问题。 “空”对象可以“初始化”,但不能使用。在完全初始化之前,无论是在构造中,还是通过使用默认构造函数和后续“init”的两步,它都不是“有效”的。
有一种广泛接受的习惯用于测试对象是否“有效”:用户定义的转换为void *
:
...
public:
operator void*() { return is_valid()? this : nullptr; }
...
其中is_valid()
可能是私有函数。有了这个,用户可以测试他的实例化对象:
class A;
A foo();
...
if (!foo) { foo.open(...); }
我知道我没有回答你的问题。我希望我提供了一些背景,让您更容易自己回答。