http://www.cppblog.com/Tveiker/archive/2011/01/08/138154.aspx本链接是“随笔”写的一篇名叫《链表实验》的文章,以下是我的分析。
我理解你说的学号的问题是:一个叫X是男性年龄是22岁的学生,假设其学号是2009000,把该学生加入到链表之后,该学生的
学号发生了变化,不再是2009000。
如果你所说的学号问题和上面的描述一致的话,该问题产生的原因是:Student类不应该有拷贝构造函数和赋值函数。
假如为了实现Student类与STL容器搭配使用的能力(要获得此种能力Student必须有拷贝构造函数和其他一些函数根据你所使用到的容器
和算法所要求的特殊函数,例如operator<)的话,这两个函数也应该换种写法,为了实现此种能力这两个函数有以下实现方法:
(1)学号的转移,参考STL的auto_ptr的控制权转移策略
以上是对你碰到问题的说明,另外从你所写的代码中还发现了一些问题和不足之处,具体详述如下:
问题
(1)Student的构造函数(Student()、Student(char *name,char* sex,int age))没有把next初始化
(2)Student的拷贝构造函数没有进行if (this != &s)的判断
(3)Student类中的Name、Sex可以不使用char*类型(之所以把这个情况说成是问题而不是不足之处是为了以后写代码是少犯与指针相关的错误)
(4)在Student类的析构函数中不能对写“Stu_no--;”这样的语句,如果想实现学号重用的能够的话就需要记录学号的使用情况(本文不讨论此问题)
不足之处
(1)形如class Student{
的代码风格不好,应该修改为
class Student
{
(2)学号不应该是一个整数并且应该隐藏学号这一重要对象的生成方式(因为学号很可能每个学校不一样,为了应对变化,所以对可能发生变化
的地方进行封装)
(3)Student类不应该包含next指针
(4)Link类中的Add函数的接口设计很不合理(在使用的时候需要先构造出一个Student,这很没有必要)
(5)Link类中的pivot作为类的成员变量不太合适并且没有多大意义
提醒你一下:请仔细思考拷贝构造函数的意义,拷贝构造的意义简单来说就是克隆,而你写的代码没有克隆好,所以的导致了学号问题
针对上述所有问题的修改方案有三种
(1)A方案:禁止拷贝构造
(2)B方案:学号转移 非法学号
各个方案的实现方法如下,其中对于学号的生成方法这二种方案都一样(为了简单起见,学号仍然采用整数)
1
/**//************************************************************************/
2
/**//* 学号生成 */
3
/**//************************************************************************/
4
5
typedef int StudentID;
6
7
class StudentIDGenerate
8

{
9
public:
10
static StudentID GenerateID()
11
{
12
return StudentBaseID++;
13
}
14
15
private:
16
static StudentID StudentBaseID;
17
};
18
19
StudentID StudentIDGenerate::StudentBaseID = 2009000;
20
21
/**//************************************************************************/
22
/**//* 链表节点 */
23
/**//************************************************************************/
24
template <typename T>
25
struct LinkNode
26

{
27
T m_value;
28
LinkNode<T> *m_pNext;
29
30
LinkNode() : m_pNext(NULL)
31
{
32
33
}
34
};
以上是通用代码,下面是方案A的代码
1
/**//************************************************************************/
2
/**//* A方案 */
3
/**//************************************************************************/
4
5
class Student
6

{
7
friend class Link;
8
9
public:
10
Student();
11
Student(string const &strName,string const &strSex, int nAge);
12
~Student();
13
14
public:
15
void display();
16
void SetValue(string const &strName,string const &strSex, int nAge);
17
int GetAge() const;
18
19
private://通过把以下函数设置为私有来实现禁止拷贝构造的能力
20
Student(const Student &);
21
Student &operator=(const Student &s);
22
23
private:
24
string m_strName;
25
int m_nAge;
26
string m_strSex;
27
StudentID m_ID;
28
};
29
30
typedef LinkNode<Student> StudentNode;
31
32
Student::Student()
33

{
34
m_ID = StudentIDGenerate::GenerateID();
35
m_nAge = 0;
36
}
37
38
Student::Student(string const &strName,string const &strSex,int nAge)
39

{
40
m_strName = strName;
41
m_strSex = strSex;
42
m_ID = StudentIDGenerate::GenerateID();
43
m_nAge = nAge;
44
}
45
46
Student::Student(const Student &s)
47

{
48
assert(false);
49
}
50
51
Student &Student::operator =(const Student &s)
52

{
53
assert(false);
54
return *this;
55
}
56
57
Student::~Student()
58

{
59
60
}
61
62
void Student::display()
63

{
64
cout<<"Name is:"<<m_strName<<" ID is:"<<m_ID<<" Sex is:"<<m_strSex<<" Age is:"<<m_nAge<<endl;
65
}
66
67
void Student::SetValue(string const &strName,string const &strSex, int nAge)
68

{
69
m_strName = strName;
70
m_strSex = strSex;
71
m_nAge = nAge;
72
}
73
74
int Student::GetAge() const
75

{
76
return m_nAge;
77
}
78
79
class Link
80

{
81
public:
82
Link();
83
~Link();
84
85
public:
86
void Delete(StudentID);
87
void Add(string const &strName,string const &strSex,int nAge);
88
void Display();
89
90
private:
91
StudentNode *m_pHead;
92
StudentNode *m_pTail;
93
};
94
95
Link::Link()//构造空链表
96

{
97
m_pHead=NULL;
98
m_pTail=NULL;
99
}
100
101
Link::~Link()//释放内存
102

{
103
while (NULL != m_pHead)
104
{
105
StudentNode *pTemp = m_pHead;
106
m_pHead = m_pHead->m_pNext;
107
delete pTemp;
108
}
109
}
110
111
void Link::Add(string const &strName,string const &strSex,int nAge)//向链表中添加学生
112

{
113
if(m_pHead==NULL)
114
{
115
m_pHead = new StudentNode();
116
m_pHead->m_value.SetValue(strName, strSex, nAge);
117
m_pTail = m_pHead;
118
m_pTail->m_pNext = NULL;
119
}
120
else
121
{
122
m_pTail->m_pNext = new StudentNode;
123
m_pTail->m_pNext->m_value.SetValue(strName, strSex, nAge);
124
m_pTail->m_pNext->m_pNext = NULL;
125
m_pTail = m_pTail->m_pNext;
126
}
127
}
128
129
void Link::Display()//显示链表中学生信息
130

{
131
cout<<endl;
132
StudentNode *pTemp = m_pHead;
133
while (NULL != pTemp)
134
{
135
pTemp->m_value.display();
136
pTemp = pTemp->m_pNext;
137
}
138
cout<<endl;
139
}
140
141
void Link::Delete(int nAge)//删除链表中所有年龄为nAge的学生
142

{
143
StudentNode *pPre = m_pHead;
144
StudentNode *pCur = m_pHead;
145
while (NULL != pCur)
146
{
147
if (pCur->m_value.GetAge() == nAge)
148
{
149
if (pCur == m_pHead)
150
{
151
pPre = m_pHead = m_pHead->m_pNext;
152
}
153
else
154
{
155
pPre->m_pNext = pCur->m_pNext;
156
}
157
158
pCur->m_value.display();
159
delete pCur;
160
pCur = NULL != pPre ? pPre->m_pNext : NULL;
161
}
162
else
163
{
164
pPre = pCur;
165
pCur = pCur->m_pNext;
166
}
167
}
168
}
以下是测试方案A的代码
void main()


{
//测试零
//vector<Student> vecStu;
//Student st1;
//vecStu.push_back(st1);

//Student st2;
//vecStu.push_back(st2);

//测试一
Link link;
link.Add("X","Boy",22);
link.Add("Y","Boy",20);
link.Add("Z","Boy",21);
link.Add("U","Girl",22);
link.Display();
link.Delete(21);
link.Display();

//测试二
Link link1;
link1.Add("X","Boy",22);
link1.Add("Y","Boy",20);
link1.Add("Z1","Boy",21);
link1.Add("Z2","Boy",21);
link1.Add("U","Girl",22);

link1.Display();
link1.Delete(21);

link1.Display();

//测试三
Link link2;
link2.Add("X","Boy",22);
link2.Add("Y","Boy",20);
link2.Add("Z1","Boy",21);
link2.Add("Z2","Boy",21);
link2.Add("U","Girl",22);

link2.Display();
link2.Delete(22);

link2.Display();

//测试四
Link link3;
link3.Add("X","Boy",22);
link3.Display();
link3.Delete(22);

link3.Display();

//测试五
Link link4;
link4.Add("X","Boy",22);
link4.Add("Y","Boy",20);
link4.Add("Z1","Boy",21);
link4.Add("Z2","Boy",21);
link4.Add("U","Girl",22);

link4.Display();
link4.Delete(1);

link4.Display();
}
其中采用方案A是测试零下面所注释掉的代码不能通过编译,在VC2008的IDE下会报:class“Student”: 没有可用的复制构造函数或复制构造函数声明为“explicit”错误
为了修正此错误,对代码就行了修改,也就是B方案
const StudentID ErrorStudentID = 0;//其实非法学号是个范围[负无穷,2009000] 添加的代码
mutable StudentID m_ID;//为了能够在拷贝构造函数中修改该值,把其类型声明为mutable 修改的代码

//修改的代码
Student::Student(const Student &s)


{
m_strName = s.m_strName;
m_strSex = s.m_strSex;
m_ID = s.m_ID;
s.m_ID = ErrorStudentID;
m_nAge = s.m_nAge;
}

//修改的代码
Student &Student::operator =(const Student &s)


{
if (this != &s)

{
m_strName = s.m_strName;
m_strSex = s.m_strSex;
m_ID = s.m_ID;
s.m_ID = ErrorStudentID;
m_nAge = s.m_nAge;
}

return *this;
}
PS:
使用面向对象语言进行程序设计的时候一个关键的问题是:设计一个好的类,这里的Student类就是一个典型的例子。
学习的时候当然可以自己写个链表,自己管理内存;但是在实际工作中还是要多用STL现成的容器和算法,只有这样才能提高代码的质量,降低错误发生的概率。
上面代码实际还可以继续进行改进,不够写道此种程度基本上没有什么大问题了。
posted on 2011-01-09 07:45
OnTheWay 阅读(1609)
评论(2) 编辑 收藏 引用 所属分类:
个人感悟