【发布时间】:2014-09-06 18:25:44
【问题描述】:
这是我明天 CS 低 div 课程的期中练习考试中的一道题。不幸的是,模拟考试没有完全正确的解决方案;此问题中显示的具体问题在 a)、b) 和 c) 部分中各获得半分。
问题是为什么他们只获得了一半的学分;如果您可以针对问题的一个或全部部分发布完整的解决方案,那将具有巨大的价值。
问题如下:
考虑一下这个代表建筑工人的普通班级的摘录。
class Worker
{
public:
Worker(string nm, string s)
: m_name(nm), m_skill(s)
{}
string name() const { return m_name; }
string skill() const { return m_skill; }
private:
string m_name;
string m_skill;
};
因为我们没有为 Worker 类声明析构函数、复制构造函数或赋值运算符,所以编译器为我们编写了这些函数。
施工人员是工人的集合。我们选择将工作人员表示为一个动态分配的指向 Workers 的指针数组。摘录如下:
class Crew
{
public:
Crew(int lim)
: m_size(0), m_maxCrewSize(lim)
{
m_crew = new Worker*[lim];
}
void hire(string nm, string s)
{
if (m_size < m_maxCrewSize)
{
m_crew[m_size] = new Worker(nm, s);
m_size++;
}
}
// other functions not shown
private:
Worker** m_crew;
int m_size;
int m_maxCrewSize;
};
m_crew 数组的第一个 m_size 元素包含指向动态分配的工人的指针;其余元素没有特殊价值。
Crew 类的用户需要复制 Crew 对象并将一个 Crew 对象分配给另一个。
对于下面的 a、b 和 c 部分,您可以根据需要实现额外的 Crew 类帮助函数。不对 Worker 类进行任何更改或添加。
一个。
完成Crew类的析构函数的实现:
Crew::~Crew()
{
for (int i=0; i<m_size; i++) {
delete m_crew[i];
}
}
b.实现 Crew 类的复制构造函数。
Crew::Crew(const Crew& original)
: m_size(original.m_size), m_maxCrewSize(original.m_maxCrewSize)
{
m_crew = new Worker*[m_maxCrewSize];
for (int i=0; i < m_size; i++) {
m_crew[i] = original.m_crew[i];
}
}
c。为 Crew 类实现赋值运算符。
Crew& Crew::operator=(const Crew& other) {
if (this != &other) {
Crew temp(*this);
m_crew = other.m_crew;
m_size = other.m_size;
m_maxCrewSize = other.m_maxCrewSize;
other.m_crew = temp.m_crew;
other.m_maxCrewSize = temp.m_maxCrewSize;
other.m_size = temp.m_size;
}
return this;
}
【问题讨论】:
-
The question is why they received only half-credit- 好吧,问问监督考试和分配分数的人。这是答案的完美来源。我知道这是无用且显而易见的,但实际上,在没有主管的观点的情况下,这主要是猜测(当然,除了一些明显的错误,如果有的话,我没有分析代码 - 我只是对原始问题做出反应)。 -
正如this reference 中解释的那样:“如果没有为类类型提供任何类型的用户定义构造函数......编译器将始终将默认构造函数声明为其类的内联公共成员。”该段的意思是,如果您在类中有任何自定义构造函数,则默认构造函数不会生成。
-
你的析构函数不完整。 m_crew 指针本身的
delete在哪里?换句话说,您在执行此操作时未能清理内存:m_crew = new Worker*[lim]; -
顺便说一句。在
operator=中,如果通过Crew temp(*this),您想进行“试运行”以检查三个部分分配期间的任何异常,那么在试运行之后,您应该以相同的顺序重做分配。如果你真的在做一次试运行,那么在实际运行中改变操作顺序会使试运行结果完全无关紧要。而且,他们的顺序看起来很奇怪。通常你首先检查最大界限,然后是实际界限,然后对项目进行操作(但这实际上是习惯性的和特定于案例的) -
另一个仅供参考:对
Worker**和int的变量进行这样的空运行是完全没有必要的。这样的分配永远不会抛出任何错误。您可以将operator=简化为简单的三行other...等等,什么?!你搞砸了它的实现。operaotr=应更改为 THIS 并从 OTHER 读取。所以最后三分之一的分配应该是this->m_crew = other.m_crew等等..
标签: c++ destructor copy-constructor assignment-operator