实验1
1.实验任务1
1 #include<iostream> 2 #include<string> 3 #include<vector> 4 5 int main() 6 { 7 using namespace std; 8 string s1; 9 string s2{ "c plus plus" }; 10 string s3{ s2 }; 11 string s4 = s2; 12 13 s1 = "oop"; 14 vector<string> v1; 15 v1.push_back(s1); 16 v1.push_back(s2 + "1"); 17 v1.push_back(s3 + "2"); 18 v1.push_back(s4 + "3"); 19 20 cout << "output1: " << endl; 21 for (auto item : v1) 22 cout << item << endl; 23 24 cout << "output2: "; 25 for (auto p = v1.begin(); p != v1.end(); ++p) 26 cout << *p << endl; 27 28 cout << "output3: " << endl; 29 for (auto i = 0; i < v1.size(); ++i) 30 cout << v1[i] << endl; 31 32 vector<string> v2{v1.rbegin(), v1.rend()}; 33 cout << "v2: " << endl; 34 for (auto item : v2) 35 cout << item << endl; 36 }
测试截图:
1 #include <iostream> 2 #include <string> 3 #include<vector> 4 #include<cmath> 5 #include<cstdlib> 6 #include<time.h> 7 8 template<typename T> 9 void output(const T& obj) 10 { 11 for (auto item : obj) 12 std::cout << item << " "; 13 std::cout << std::endl; 14 } 15 16 int main() 17 { 18 using namespace std; 19 20 vector<int> v1{ 1,9,8,4 }; 21 v1.insert(v1.begin(), 2022); 22 v1.insert(v1.end(), 2023); 23 24 cout << "v1: "; 25 output(v1); 26 27 v1.pop_back(); 28 v1.erase(v1.begin()); 29 cout << "v1: "; 30 output(v1); 31 32 vector<string> v2{ "《1984》","《动物农场》","《美丽新世界》》" }; 33 cout << "v2: "; 34 output(v2); 35 }
测试截图:
实验任务2
1 #include <iostream> 2 using std::cout; 3 using std::endl; 4 5 class Point { 6 public: 7 Point(int x0 = 0, int y0 = 0); 8 Point(const Point& p); 9 ~Point() = default; 10 int get_x() const { return x; } 11 int get_y() const { return y; } 12 void show() const; 13 private: 14 int x, y; 15 }; 16 17 Point::Point(int x0, int y0) : x{ x0 }, y{ y0 } { 18 cout << "constructor called." << endl; 19 } 20 21 Point::Point(const Point& p) : x{ p.x }, y{ p.y } { 22 cout << "copy constructor called." << endl; 23 }void Point::show() const { 24 cout << "(" << x << ", " 25 << y << ")" << endl; 26 } 27 int main() { 28 Point p1(4, 5); 29 p1.show(); 30 Point p2 = p1; 31 p2.show(); 32 Point p3{ p2 }; 33 p3.show(); 34 cout << p3.get_x() << endl; 35 }
原数据测试截图:
更换数据后测试截图
实验任务3
1 #include<iostream> 2 #include<iomanip> 3 4 using std::cout; 5 using std::endl; 6 7 class Clock { 8 public: 9 Clock(int h = 0, int m = 0, int s = 0); 10 Clock(const Clock& t); 11 ~Clock() = default; 12 13 void set_time(int h, int m = 0, int s = 0); 14 void show_time() const; 15 private: 16 int hour, minute, second; 17 }; 18 19 Clock::Clock(int h, int m, int s) : hour{ h }, minute{ m }, second{ s } { 20 cout << "constructor called" << endl; 21 } 22 Clock::Clock(const Clock& t) : hour{ t.hour }, minute{ t.minute }, 23 second{ t.second } { 24 cout << "copy constructor called" << endl; 25 } 26 void Clock::set_time(int h, int m, int s) { 27 hour = h; 28 minute = m; 29 second = s; 30 } 31 void Clock::show_time() const { 32 using std::setw; 33 using std::setfill; 34 cout << setfill('0') << setw(2) << hour << ":" 35 << setw(2) << minute << ":" 36 << setw(2) << second << endl; 37 } 38 Clock reset() { 39 return Clock(0, 0, 0); 40 } 41 int main() 42 { 43 Clock c1(12, 0, 5); 44 c1.show_time(); 45 c1 = reset(); 46 c1.show_time(); 47 Clock c2(c1); 48 c2.set_time(6); 49 c2.show_time(); 50 }
原数据测试截图:
更换数据后测试截图:
实验任务4
1 #include <iostream> 2 3 class X { 4 public: 5 X(); 6 ~X(); 7 X(int m); 8 X(const X& obj); 9 X(X&& obj) noexcept; 10 void show() const; 11 private: 12 int data; 13 }; 14 X::X() : data{ 42 } { 15 std::cout << "default constructor called.\n"; 16 } 17 X::~X() { 18 std::cout << "destructor called.\n"; 19 } 20 X::X(int m) : data{ m } { 21 std::cout << "constructor called.\n"; 22 } 23 X::X(const X& obj) : data{ obj.data } { 24 std::cout << "copy constructor called.\n"; 25 } 26 X::X(X&& obj) noexcept : data{ obj.data } { 27 std::cout << "move constructor called.\n"; 28 } 29 void X::show() const { 30 std::cout << data << std::endl; 31 } 32 int main() { 33 X x1; 34 x1.show(); 35 X x2{ 2049 }; 36 x2.show(); 37 X x3{ x1 }; 38 x3.show(); 39 X x4{ std::move(x2) }; 40 x4.show(); 41 }
测试结果截图
分析:
一、构造函数调用情况分析:
line33 默认构造函数 X();被调用;
line35 构造函数 X(int m);被调用;
line37 复制构造函数 X(const X& obj);被调用
line39 移动构造函数 X(X&& obj) noexcept;被调用
二、析构函数调用情况分析:
该实验任务中,析构函数位于line6:~X(); 析构函数是在对象的生存期即将结束的时刻自动调用的。
在本实验任务中,即于主函数语句全部执行完后,对象x1,x2,x3,x4的生存期结束,分别调用四次析构函数,用于清理相应的内存空间。但值得注意的是,析构函数调用顺序与构造顺序正好相反,即对象x4,x3,x2,x1依次调用析构函数。
实验任务五
1 #include <iostream> 2 #include <iomanip> 3 4 //创建矩形对象 5 class Rectangle { 6 private: 7 double length, width; //数据成员 8 public: 9 Rectangle(); //默认构造函数 10 Rectangle(double l, double w); //默认构造函数 11 Rectangle(Rectangle& r); //复制构造函数 12 ~Rectangle(); //析构函数 13 14 //各普通函数成员 15 double len()const { return length; } 16 double wide()const { return width; } 17 double area()const { return length * width; } 18 double circumference()const { return 2 * length + 2 * width; } 19 void resize(double times) { length *= times; width *= times; } 20 void resize(double l_times, double w_times) { length *= l_times; width *= w_times; } 21 }; 22 23 // 矩形类Rectangle的定义和实现 24 Rectangle::Rectangle() :length(2.0), width(1.0){}; 25 Rectangle::Rectangle(double l, double w) :length(l), width(w){}; 26 Rectangle::~Rectangle() {}; 27 Rectangle::Rectangle(Rectangle& r) 28 { 29 length = r.length; 30 width = r.width; 31 } 32 33 // 普通函数, 用于输出矩形信息 34 void output(const Rectangle& rect) { 35 using namespace std; 36 cout << "矩形信息: \n"; 37 cout << fixed << setprecision(2); // 控制输出格式:以浮点数形式输出、小数部分保留两位 38 cout << "长:" << setw(10) << rect.len() << endl; 39 cout << "宽:" << setw(10) << rect.wide() << endl; 40 cout << "面积:" << setw(8) << rect.area() << endl; 41 cout << "周长:" << setw(8) << rect.circumference() << endl<<endl; 42 } 43 44 // 主函数,测试Rectangle类 45 int main() { 46 Rectangle rect1; // 默认构造函数被调用 47 output(rect1); 48 Rectangle rect2(10, 5); // 带有两个参数的构造函数被调用 49 output(rect2); 50 Rectangle rect3(rect1); // 复制构造函数被调用 51 rect3.resize(2); // 矩形rect3的长和宽同时缩放2倍 52 output(rect3); 53 rect3.resize(5, 2); // 矩形rect3的长缩放5倍, 宽缩放2倍 54 output(rect3); 55 }
测试结果截图:
实验总结
在编写实验任务五时,于line38~line41中调用成员函数,发现调用的四个成员函数len(),wide(),area(),circumference()均出现错误提醒,显示“对象含有与成员函数不兼容的类型限定符”。后经搜索与探究发现,是在声明四个成员函数时,未用const关键字修饰。因为普通输出函数output的参数列表中用const修饰,这说明函数不允许修改这个参数,const对象是无法调用非const成员函数的,在调用其他成员函数时只能调用有const修饰的成员函数。
在学习C++的过程中,发现const关键字经常出现,但对其却没有较深的理解与良好的运用。通过探究学习,发现C++中,const关键字的运用十分灵活,无论是函数参数,还是函数返回值,还是函数末尾都经常会看到const关键字,合理地使用const关键词能大大提高程序的健壮性。
const关键字的作用总结如下:
1.可以用来修饰变量,修饰函数参数,修饰函数返回值,且被const修饰的东西,都受到强制保护,可以预防其它代码无意识的进行修改,从而提高了程序的健壮性;
2.使编译器保护那些不希望被修改的参数,防止无意代码的修改,减少bug;
3.增强代码的可读性,给读代码的人传递有用的信息,声明一个参数,是为了告诉用户这个参数的应用目的。
4.可以节省空间,避免不必要的内存分配。
const关键字的用法:
1.定义常量
常量在定义时必须赋值,声明后在整个程序运行期间其值固定,不能再发生变化,否则是非法的,编译器无法通过。
2.在函数中使用
(1)const修饰函数参数
a.传递过来的参数在函数内不可改变;
b.参数指针所指内容为常量不可变;
c.参数指针本身为常量不可变;
d.参数为引用,为了增加效率同时防止修改。
(2)const修饰函数返回值
多用于操作符的重载。
3.在类中使用
(1)const修饰成员变量
const修饰类的成员函数,表示成员变量,不能被修改,同时它只能在初始化列表中赋值;
(2)const修饰成员函数
const修饰类的成员函数,则该成员函数不能修改类中任何非const成员函数。一般写在函数的最后来修饰