实验内容

利用C++语言,参考教材,实现Triangular类开发与测试,包括:

  • 构造函数、析构函数
  • 数据成员定义、函数成员定义
  • 利用运算符重载技术,实现Iterator
  • 给出实验结果截图及实验分析

实验原理

2.1 类的基本结构包含哪些部分

关键字,类名,访问修饰符,变量,方法。

类定义是以关键字 class 开头,后跟类的名称。类的主体是包含在一对花括号中。类定义后必须跟着一个分号或一个声明列表。

关键字 public 确定了类成员的访问属性。在类对象作用域内,公共成员在类的外部是可访问的。您也可以指定类的成员为 private 或 protected。

2.2 构造函数、析构函数的特点、用法分析

类的构造函数是一种特殊的函数,在创建一个新的对象时调用。类的析构函数也是一种特殊的函数,在删除所创建的对象时调用。

构造函数的名称与类的名称是完全相同的,并且不会返回任何类型,也不会返回 void。构造函数可用于为某些成员变量设置初始值。

析构函数的名称与类的名称是完全相同的,只是在前面加了个波浪号(~)作为前缀,它不会返回任何值,也不能带有任何参数。析构函数有助于在跳出程序(比如关闭文件、释放内存等)前释放资源。

2.3

运算符重载,说白了就是重新定义原有的运算符以适合泛型指针类的运算。可以像定义成员函数那样重新定义运算符。

运算符函数很像普通函数,但是运算符函数不用指定函数名。只需要在运算符前加上关键字 operator 即可。

重载规则:

  1. . .* :: ?: 这四个运算符不能重载

  2. 运算符的操作数个数不能变。例如“==”只能有两个操作数

  3. 运算符的优先级不能变

  4. 运算符函数的参数列表中,至少有一个参数为 class 类型。这是人为定义的。

  5. 人为区分了i和i的运算符重载方式

嵌套类型:

Typedef可以为某个类型设定另一个不同的名称。

代码

Triangular.h

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
#include "triangularIterator.h"
#include <vector>
#include <ostream>
#include <iostream>
using namespace std;
class trianguluarIterator;
class Triangular {
public:
static vector<int> _elems;
friend class trianguluarIterator; //作为Triangular类的iterator友元, 可访问private中的成员;
typedef trianguluarIterator iterator;
Triangular(int len = 1, int bp = 1);
Triangular(const Triangular &);
Triangular &operator=(const Triangular &rhs);
//3个构造函数;
int length() const { return _length; }
int beg_pos() const { return _beg_pos; }
int elem(int pos) const;
//获取vector长度, 起始位置, pos位置的元素值;
void length(int nlen) { _length = nlen; }
void beg_pos(int npos) { _beg_pos = npos; }
//更改Triangular的长度大小和起始位置;
bool next(int &val) const;
void next_reset() const { _next = 1; }
//获取元素值和重置_next指针;
static bool is_elem(int);
static void gen_elements(int length);
static void gen_elems_to_value(int value);
static void display(int length, int beg_pos, ostream &os = cout);
//只能访问静态成员, 此处访问的是成员vector<int> _elems;

triangularIterator begin() const {
return triangularIterator(_beg_pos);
}
triangularIterator end() const {
return triangularIterator(_beg_pos + _length);
}

private:
int _length;
int _beg_pos;
mutable int _next;
enum {
_max_elems = 1024
};
};

Triangular.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
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
#include "Triangular.h"

ostream &operator<<(ostream &os, const Triangular &rhs) {
os << "( " << rhs.beg_pos() << " , " << rhs.length() << " ) ";
rhs.display(rhs.length(), rhs.beg_pos(), os);
return os;
}

istream &operator>>(istream &is, Triangular &rhs) {
char ch1, ch2;
int bp, len;

is >> ch1 >> bp >> ch2 >> len;
rhs.beg_pos(bp);
rhs.length(len);
rhs.next_reset();
return is;
}

Triangular::Triangular(int len, int beg_pos) : _length(len > 0 ? len : 1), _beg_pos(beg_pos > 0 ? beg_pos : 1) {
_next = _beg_pos;
int elem_cnt = _beg_pos + _length;
if (_elems.size() < elem_cnt) {
gen_elements(elem_cnt);
}
}

Triangular::Triangular(const Triangular &rhs) : _length(rhs._length), _beg_pos(rhs._beg_pos), _next(rhs._next) {
}

//计算所有元素之和
int sum(const Triangular &trian) {
if (0 == trian.length()) {
return 0;
}
int val, sum = 0;
trian.next_reset(); //重置为起点开始累加;
while (trian.next(val)) {
sum += val;
}
return sum;
}

int Triangular::elem(int pos) const {
return _elems[pos - 1];
}

bool Triangular::next(int &value) const {
if (0 == _next) {
return false;
}
if (_next < _beg_pos + _length) {
value = _elems[_next++];
return true;
}
_next = 0;
return false;
}

Triangular &Triangular::operator=(const Triangular &rhs) {
if (this != &rhs) {
_length = rhs._length;
_beg_pos = rhs._beg_pos;
_next = 1;
}
return *this;
}

vector<int> Triangular::_elems; //定义一个静态vector;

bool Triangular::is_elem(int value) {
if (!_elems.size() || _elems[_elems.size() - 1] < value) {
gen_elems_to_value(value);
}
return find(_elems.begin(), _elems.end(), value) != _elems.end();
}

void Triangular::gen_elements(int length) {
if (length < 0 || length > _max_elems) {
cerr << "Triangular Sequence: oops: invalid size: ";
cerr << length << " -- max size is ";
cerr << _max_elems << endl;
return;
}
if (_elems.size() < length) {
int ix = _elems.size() ? _elems.size() + 1 : 1;
while (ix <= length) {
_elems.push_back(ix * (ix + 1) / 2); //添加元素直到vector长度大于等于length;
++ix;
}
}
}

void Triangular::gen_elems_to_value(int value) {
int ix = _elems.size();
if (0 == ix) {
_elems.push_back(1);
ix = 1;
}
while (_elems[ix - 1] < value && ix < _max_elems) {
_elems.push_back(ix * (ix + 1) / 2); //添加元素到vector中直到大于等于value;
++ix;
}
if (ix == _max_elems) {
cout << "Triangular Sequence: oops: value too large " << endl;
cout << value << " -- exceeds max size of " << endl;
cout << _max_elems << endl;
}
}

void Triangular::display(int length, int beg_pos, ostream &os) {
if (length <= 0 || beg_pos <= 0) {
cout << "invalid parameters -- unable to fulfill request: ";
cout << length << ", " << beg_pos << endl;
return;
}
int elems = beg_pos + length - 1;
if (_elems.size() < elems) {
gen_elements(elems);
}
for (int ix = beg_pos - 1; ix < elems; ++ix) {
os << _elems[ix] << ' ';
}
}

triangularIterator.h
class triangularIterator {
public:
triangularIterator(int index) : _index(index - 1) {} //构造函数初始化iterator;
bool operator==(const triangularIterator &) const; //比较iterator是否相等;
bool operator!=(const triangularIterator &) const; //比较iterator是否不相等;
int operator*() const; //指针解引用运算符;
triangularIterator &operator++(); //前置自增运算符;
triangularIterator operator++(int); //后置自增运算符;

private:
int _index;
};

triangularIterator.cpp
#include "Triangular.h"
bool triangularIterator::operator==(const triangularIterator &rhs) const {
return _index == rhs._index; //判断2个Triangular类是否相等;
}

bool triangularIterator::operator!=(const triangularIterator &rhs) const {
return !(*this == rhs); //使用重载过的==运算符的非运算;
}

int triangularIterator::operator*() const {
return Triangular::_elems[_index]; //获取_index索引中的元素;
}

triangularIterator &triangularIterator::operator++() {
++_index; //递增下标;
return *this; //返回新值;
}

triangularIterator triangularIterator::operator++(int) {
triangularIterator tmp = *this; //存储先前值;
++_index; //递增下标;
return tmp; //返回先前值;
}

main.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>
#include "Triangular.h"

int main() {
cout << "input length a and begin_pos b:" << endl;
int a, b;
cin >> a >> b;
Triangular tri(a, b);
triangularIterator it = tri.begin();
triangularIterator end_it = tri.end();
cout << "Triangular Series of " << tri.length() << " elements\n";
Triangular::display(tri.length(), tri.beg_pos(), cout);
while (it != end_it) {
cout << *it << ' ';
++it;
}
cout << endl;
return 0;
}

实验结果及分析

输入10和5

image-20221123165039978

输入29和21

image-20221123165106807

输入100和100

image-20221123165122101

综上,可以发现重载的运算符++, --, !=, ==, 以及*(指针间接引用)完美运行。