STL学习笔记一

STL学习笔记一

实验任务

  1. 以公司和员工类和查找收入最高员工任务为例,学习建立多文件项目,编译并运行

  2. 以月薪制员工为例,学习并实践C++中的继承

    1. 为员工派生类实现input方法
    2. 在此基础上为公司类实现findBestPaid方法
    3. 最后在主函数中测试你的实现,达到查找月薪制最高收入员工的目的
  3. 为员工类重载>和=运算符,在此基础上重写公司类的findBestPaid方法,从而提高程序的可读性。在主函数中进行测试。

示范代码

头文件,包含了公司类和员工类的声明

->公司类
1
2
3
4
5
6
7
8
9
10
11
12
class Company
{
private:
Employee bestPaid;
ListTemp<Employee> empContainer;

public:
void inputEmployee(); //when input employee from keyboard, store the input data in the container for later use;
void findBestPaid(); //go through the container to find the best paid employee
void printBestPaid() const;
void findBestPaidReverse();
};
->员工类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
class Employee
{
private:
std::string name;
double grossPay;

public:

// Postcondition: this employee's name has been set to ""
// and gross pay to 0.00.
Employee();


// Postcondition: The name and gross pay of this Employee have
// been read in.
void input();


// Postcondition: this Employee's name and gross pay have been
// written out.
void output() const;


// Postcondition: this Employee contains a copy of otherEmployee.
//void copy(const Employee& otherEmployee);
void operator=(const Employee& otherEmployee);


// Postcondition: true has been returned if this Employee's gross
// pay is greater than that of otherEmployee.
// Otherwise, false has been returned.
bool operator>(const Employee& otherEmployee) const;

std::string getName() const;

};
->储存员工用的链表
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
template<class T>
class ListTemp
{
private:
struct Node
{
T data;
Node* next;
Node* prev;
};

Node *head;
Node *tail;
int size;

public:

ListTemp(); //constructor

~ListTemp(); //destructor

int getLength() const; //get the number of elements

bool isEmpty() const; //check whether the container is empty

// Postcondition: A node with newData has been inserted at the
// head of the Linked container.
void addHead(const T& newData);
void addTail(const T& newData);

//************************declaration of the inner iterator class****************************
class Iterator
{
friend class ListTemp<T>; //friend class of the iterator class
private:
Node *curr;

// Postcondition: The iterator has been constructed from ptr.
Iterator(Node *ptr); //constructor with Node parameter, defined as private

public:

// Postcondition: The iterator has been constructed.
Iterator(); //default constructor

// Precondition: The iterator is positioned at an item.
// Postcondition: The iterator has been positioned at
// the next item in the Linked object.
Iterator operator++(int); //post-increment of ++

typename ListTemp<T>::Iterator operator--(int);

// Postcondition: A reference to the item the iterator
// is positioned at has been returned.
T& operator*() const;

// Postcondition: true has been returned if the
// iterator is equal to other; otherwise,
// false has been returned.
bool operator==(const Iterator other) const;

};//class Iterator


// Postcondition: An iterator positioned at the head of
// the Linked container has been returned.
Iterator Begin() const;

// Postcondition: An iterator positioned just AFTER the
// tail of the Linked container has been
// returned. NOT the position at the tail!
Iterator End() const;

};


//************************implementation of the iterator inner class**************************
template<class T>
ListTemp<T>::Iterator::Iterator()
{
curr = NULL;
}

template<class T>
ListTemp<T>::Iterator::Iterator(Node *ptr)
{
curr = ptr;
}

template<class T>
typename ListTemp<T>::Iterator ListTemp<T>::Iterator::operator++(int)
{
Iterator temp = *this; //default copy constructor
this->curr = curr->next;
return temp; //return iterator object
}
template<class T>
typename ListTemp<T>::Iterator ListTemp<T>::Iterator::operator--(int)
{
Iterator temp = *this; //default copy constructor
this->curr = curr->prev;
return temp; //return iterator object
}


template<class T>
T& ListTemp<T>::Iterator::operator*() const
{
return curr->data; //return data reference
}

template<class T>
bool ListTemp<T>::Iterator::operator==(const Iterator other) const
{
return curr == other.curr;
}


//************************implementation of the Begin and End position**************************
template<class T>
typename ListTemp<T>::Iterator ListTemp<T>::Begin() const
{
return Iterator(head); //container class call the private method (constructor) of the Iterator class:
//friend class is required
}

template<class T>
typename ListTemp<T>::Iterator ListTemp<T>::End() const
{
return Iterator(tail); //NULL pointer
}


//************************implementation of the linked list class template**************************
template<class T>
ListTemp<T>::ListTemp()
{
head = NULL;
tail = NULL;//empty list
size = 0;
}


template<class T>
ListTemp<T>::~ListTemp()
{
Node *current = head;
Node *temp = NULL;
while (current != NULL)
{
temp = current;
current = current->next;
delete temp; //release
}
}


template<class T>
int ListTemp<T>::getLength() const
{
return size;
}


template<class T>
bool ListTemp<T>::isEmpty() const
{
return size == 0;
}


template<class T>
void ListTemp<T>::addHead(const T& newData)
{
//please implement this
if (getLength()==0)
{
Node* newHead = new Node;
newHead->data = newData;
newHead->next = head;
head = newHead;
tail = newHead;
size++;
}
else{
Node* newHead = new Node;
newHead->data = newData;
head->prev = newHead;
newHead->next = head;
head = newHead;
size++;
}
}
template<class T>
void ListTemp<T>::addTail(const T& newData)
{
Node* newTail = new Node;
newTail->data = newData;
tail->next = newTail;
newTail->prev = tail;
tail = newTail;
size++;

}

cpp文件,包含了头文件的具体实现以及测试用的主程序

->公司类的实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#include "company.h"

void Company::inputEmployee()
{
//please implement this
Employee employee;
employee.input();
empContainer.addHead(employee);
while (1)
{
employee.input();
if (employee.getName() != "*")
empContainer.addHead(employee);
else break;
}
}

void Company::findBestPaid()
{
//please implement this

}
void Company::findBestPaidReverse()
{
ListTemp<Employee>::Iterator itr(empContainer.End());
for (int i = 0;i < empContainer.getLength();i++)
{
if (*itr > bestPaid)
{
bestPaid = *itr;
}
itr--;
}
}
void Company::printBestPaid() const
{
cout << "The best-paid employee and gross pay: " << endl;
bestPaid.output();
} // printBestPaid
->员工类的实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include "employee.h"

Employee::Employee()
{
name = "";
grossPay = 0;
} // default constructor


void Employee::input()
{
cout << "Please enter a name and gross pay; to quit, enter * followed by any number: ";
cin >> name >> grossPay;
} // input


void Employee::output() const
{
cout << "name: " << name << "; gross pay: " << grossPay << endl;
} // output


string Employee::getName() const
{
return name;
}
->测试用主程序
1
2
3
4
5
6
7
8
9
10
11
#include "company.h"

int main()
{
Company cmp;
cmp.inputEmployee();
cmp.findBestPaidReverse();
cmp.printBestPaid();

return 0;
}

解决代码

input方法在示范代码中已经给出

->findBestPaid方法
1
2
3
4
5
6
7
8
9
10
11
12
13
void Company::findBestPaid()
{
//please implement this
ListTemp<Employee>::Iterator itr(empContainer.Begin());
for (int i = 0;i < empContainer.getLength();i++)
{
if (*itr > bestPaid)
{
bestPaid = *itr;
}
itr++;
}
}

使用了链表中的迭代器来进行遍历

->两个操作符的重载
1
2
3
4
5
6
7
8
9
10
11
void Employee::operator=(const Employee &otherEmployee)
{
name = otherEmployee.name;
grossPay = otherEmployee.grossPay;
}

bool Employee::operator>(const Employee &otherEmployee) const
{
return this->grossPay > otherEmployee.grossPay;
} // compare

->月薪制员工的声明和实现 声明
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include "employee.h"

class HourlyEmployee :public Employee
{
public:
HourlyEmployee();

void readInto();

bool isSentinel() const;

protected:
int hoursWorked;
double payRate;
const static int HOURS_WORKED_SENTINEL;
const static double PAY_RATE_SENTINEL;
};

定义

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include<iostream>
#include "hourlyemployee.h"

const int HourlyEmployee::HOURS_WORKED_SENTINEL = -1;
const double HourlyEmployee::PAY_RATE_SENTINEL = -1.00;


void HourlyEmployee::readInto()
{
cout << "Please enter a name, hours worked and pay rate. The sentinels are"
<< NAME_SENTINEL << " "
<< HOURS_WORKED_SENTINEL << " " << PAY_RATE_SENTINEL << ":";
cin >> name >> hoursWorked >> payRate;

grossPay = hoursWorked * payRate;//在数据输入的时候
}

bool HourlyEmployee::isSentinel()const
{
if (name == NAME_SENTINEL && hoursWorked == HOURS_WORKED_SENTINEL
&& payRate == PAY_RATE_SENTINEL)
return true;
else
return false;

}

思考随笔

在你完成本次实验的过程中,查找到的收入最高的雇员(按月付酬,HourlyEmployee类型)为什么能够赋值给bestPaid?)
按月付酬的HourlyEmployee对象是由employee类继承而来的,根据“is-a”原则,该对象也是一个employee类的实例对象,因此与同为employee类对象的bestPaid其实是同一个类的对象,属于同一种数据类型,所以可以相互赋值,满足了赋值相容原则。