2013年上半年软件设计师C++题答案与分析
昨天刚考了软件设计师,由于目前我正在学习C++的使用,所以对下午的C++试题比较感兴趣,回来就根据记忆,把自己的答案,写了出来,然后重新推理了一下源程序,测试编译运行,最后对答案进行了分析。
原题意是写一个自动写简历的程序,是按原型模式进行设计的。
根据记忆整理,并进行改动后可以编译运行的程序如下:
#include <iostream>
#include <string>
using namespace std;
class Cloneable
{
public:
//(1);
virtual Cloneable * Clone() = 0 ;
};
class WorkExperience : public Cloneable
{
private:
string time;
string workExp;
public:
int setTime(string time){
this->time=time;
cout << "WorkExperience setTime:" << time << endl ;
}
int setWorkExp(string workExp){}
Cloneable * Clone()
{
cout << "WorkExperience" << " Clone" << endl;
//(2);
WorkExperience * obj = new WorkExperience();
obj->time=this->time;
obj->workExp=this->workExp;
cout << "WorkExperience" << " Clone ok." << endl;
return obj;
}
};
class Resume : public Cloneable
{
private:
string name,sex;
int age;
WorkExperience * work;
Resume(WorkExperience * work)
{
cout << "Resume :" << " Resume(WorkExperience)" << endl;
//this->work=(3);
this->work=(WorkExperience *)(work->Clone());//work;//
}
public:
Resume(string name){
cout << "Resume " << " Resume(" << name << ")" << endl;
this->name=name;
this->work=NULL;
this->age=-1;
}
~Resume(){
cout << "Resume " << " destructor " << endl;
if(work!=NULL)
{
delete work;
cout << "Resume " << " delete work " << endl;
}
}
int setSex(string sex){
this->sex=sex;
cout << "Resume setSex:" << sex << endl ;
}
int setAge(int age){
this->age=age;
cout << "Resume setAge:" << age << endl ;
}
int setWorkExperience(WorkExperience * work){
cout << "Resume " << " setWorkExperience" << endl;
this->work=(WorkExperience *)(work->Clone());
}
Cloneable * Clone()
{
cout << "Resume " << "Clone" << endl;
//(4);
Resume * obj = new Resume(this->work);
obj->name=this->name;
obj->sex=this->sex;
obj->age=this->age;
cout << "Resume " << "Clone ok." << endl;
return obj;
}
};
int main()
{
cout << "Prototype test" << endl ;
Resume * a= new Resume("lintax");
WorkExperience * work=new WorkExperience();
a->setSex("男");
a->setAge(36);
work->setTime("2000-2003");
a->setWorkExperience(work);
work->setTime("2003-2005");
a->setWorkExperience(work);
//Resume * b= (5);
Resume * b= (Resume *)a->Clone();
work->setTime("2005-2013");
b->setWorkExperience(work);
delete b;
delete a;
delete work;
return 0;
}
下面给出我分析后的答案:
1、virtual Cloneable * Clone() = 0
2、WorkExperience * obj = new WorkExperience()
3、(WorkExperience *)(work->Clone())
4、Resume * obj = new Resume(this->work)
5、(Resume *)(a->Clone())
分析如下:
1,C++题考虚函数似乎是惯例了,做过往年真题的同学应该有体会的。类Cloneable 基本上就是一个接口类,他的主要用途就是声明一个Clone()函数,这个其实也是原型模式的概念所在,就是实现拷贝。由于希望所有子类进行重写Clone()函数,所以定义为虚函数。具体函数名、返回类型什么的,参考子类里面的Clone函数的实现就可以知道了。
2,在WorkExperience 的Clone函数种,obj没有定义就开始使用了,不合理,所以就需要在空白处进行定义。定义为什么类型?看obj有WorkExperience类的成员,那么也就确定obj即WorkExperience类的对象。由于Clone函数没有传入的参数,而要传出obj,则obj需要有真实指向的内容,就需要new一个了。
3,这个题我开始一看,很明显的一个赋值操作,似乎函数也非常简单,也没有其它输入参数 ,好像直接赋值work就行了。这样编译也是可以通过的。可是,考官会给我们送分吗?只怕没有那么幸福的事情。再联系原型模式的概念,它是要进行完整的拷贝,而不是仅仅指向就行了的。所以,这里要进行一次Clone。这里又要注意,对于C++,编译是比较严格的,等号前后的类型若不匹配,是会编译报警甚至报错的。这里,我添加了强制类型转换,不清楚考官会否要求类型匹配。
4,这题与第2题类似,可是不要掉以轻心,Resume提供了两个构造函数,考虑到Resume类的Clone函数要实现全部内容的拷贝,所以只能选择前一个构造函数Resume(WorkExperience * work)。参数选择,个人感觉使用work或者this->work都可以,因为在这个函数里面,并没有关于work名字的冲突问题。
5,这题与第3题类似,不过要注意的,一个是类型匹配,很容易被忽略的。另外一点是其选择范围更大,似乎也可以新建一个类,可是这样,就与题意不相符了。使用一次Clone,是将前面简历的内容拷贝了一份,在新生成的Resume对象里面,就有了所有原来的对象(a)的内容,又可以继续添加新的内容,且新的对象b没有对原对象a的依赖--即对象a即使删除了,也不影响对象b的继续使用。
不分析不知道,一分析吓一跳,根据我的分析,我竟然已经错了两个,本来还以为已经考虑的比较充分了,原来还是不够小心啊!
总的感觉,每一题都考到了不同的内容,题目的难度是一年比一年大了。
以上,仅供参考,欢迎讨论。