实验二
task1
(1)
1 #pragma once 2 3 #include<string> 4 5 //类T:声明 6 class T{ 7 //对象属性、方法 8 public: 9 T(int x=0,int y=0);// 普通构造函数 10 T(const T &t);// 复制构造函数 11 T(T &&t); // 移动构造函数 12 ~T();// 析构函数 13 14 void adjust(int ratio);// 按系数成倍调整数据 15 void display() const;// 以(m1, m2)形式显示T类对象信息 16 17 private: 18 int m1,m2; 19 // 类属性、方法 20 public: 21 static int get_cnt();// 显示当前T类对象总数 22 23 public: 24 static const std::string doc; // 类T的描述信息 25 static const int max_cnt; 26 27 private: 28 static int cnt;// 当前T类对象数目 29 30 // 类T友元函数声明 31 friend void func(); 32 }; 33 34 // 普通函数声明 35 void func();
1 #include"T.h" 2 #include<iostream> 3 #include<string> 4 5 //类T实现 6 7 // static成员数据类外初始化 8 const std::string T::doc{"a simple class sample"}; 9 const int T::max_cnt=999; 10 int T::cnt=0; 11 12 //类方法 13 int T::get_cnt(){ 14 return cnt; 15 } 16 17 // 对象方法 18 T::T(int x,int y):m1{x},m2{y}{ 19 ++cnt; 20 std::cout<<"T constructor called.\n"; 21 } 22 23 T::T(const T &t):m1{t.m1},m2{t.m2}{ 24 ++cnt; 25 std::cout<<"T copy constructor called.\n"; 26 } 27 28 T::T(T &&t):m1{t.m1},m2{t.m2}{ 29 ++cnt; 30 std::cout<<"T move constructor called.\n"; 31 } 32 T::~T(){ 33 --cnt; 34 std::cout<<"T destructor called.\n"; 35 } 36 37 void T::adjust(int ratio){ 38 m1*=ratio; 39 m2*=ratio; 40 } 41 void T::display() const{ 42 std::cout<<"("<<m1<<","<<m2<<")"; 43 } 44 45 // 普通函数实现 46 void func(){ 47 T t5(42); 48 t5.m2=2049; 49 std::cout<<"t5="; 50 t5.display(); 51 std::cout<<'\n'; 52 }
1 #include"T.h" 2 #include<iostream> 3 4 void test_T(); 5 6 int main(){ 7 std::cout<<"test Class T:\n"; 8 test_T(); 9 10 std::cout<<"\ntest friend func:\n"; 11 func(); 12 } 13 14 void test_T(){ 15 using std::cout; 16 using std::endl; 17 18 cout<<"T info:"<<T::doc<<endl; 19 cout<<"T objects'max count:"<<T::max_cnt<<endl; 20 cout<<"T objects'current count:"<<T::get_cnt()<<endl<<endl; 21 22 T t1; 23 cout<<"t1=";t1.display();cout<<endl; 24 25 T t2(3,4); 26 cout<<"t2=";t2.display();cout<<endl; 27 28 T t3(t2); 29 t3.adjust(2); 30 cout<<"t3=";t3.display();cout<<endl; 31 32 T t4(std::move(t2)); 33 cout<<"t4=";t4.display();cout<<endl; 34 35 cout<<"test:T objects'current count:"<<T::get_cnt()<<endl; 36 }
(2)运行结果截图

(3)问题一:

原因:func()函数未声明。
问题二:T(int x=0,int y=0)是普通构造函数且带默认参数,它的功能是如果调用时没有参数,则用默认值。调用机制:当以非拷贝和非移动的方式创建对象时。
T(const T &t)是复制构造函数,功能是使用一个已存在的对象来初始化同类的一个新对象。调用时机:①当用类的一个对象去初始化该类的另一个对象时。②如果函数的形参是类的对象,调用函数时,进行形参和实参结合时。③如果函数的返回值是类的对象,函数执行完成返回调用者时。
T(T &&t);是移动构造函数。功能是使用一个右值引用来初始化新对象,将资源从源对象移动到新对象,源对象不再拥有资源。调用时机:从函数返回一个临时对象时。
~T();是析构函数,功能是用来完成对象被删除前的一些清理工作。调用世纪:在对象的生存期即将结束的时刻被自动调用的。
问题三:可以正确编译。
task2
(1)
1 #pragma once 2 #include<string> 3 4 class Complex{ 5 public: 6 static const std::string doc; 7 8 Complex(double xx=0,double yy=0); 9 Complex(const Complex &t); 10 Complex(Complex &&t); 11 ~Complex()=default; 12 13 Complex &operator=(const Complex &m1); 14 void add(const Complex &m1); 15 double get_real() const; 16 double get_imag() const; 17 private: 18 double x,y; 19 }; 20 21 double abs(const Complex &c); 22 void output(const Complex &c); 23 Complex add(const Complex &c1,const Complex &c2); 24 bool is_equal(const Complex &a,const Complex &b); 25 bool is_not_equal(const Complex &a,const Complex &b);
1 #include"Complex.h" 2 #include<iostream> 3 #include<cmath> 4 5 const std::string Complex::doc="a simplified complex class"; 6 7 Complex::Complex(double xx,double yy):x(xx),y(yy){} 8 9 Complex::Complex(const Complex &t):x(t.x),y(t.y){} 10 11 Complex::Complex(Complex &&t):x(t.x),y(t.y){} 12 13 Complex& Complex::operator=(const Complex &m1){ 14 if(this!=&m1) 15 { 16 x=m1.x; 17 y=m1.y; 18 } 19 return *this; 20 } 21 22 double Complex::get_real() const{return x;} 23 24 double Complex::get_imag() const{return y;} 25 26 void Complex::add(const Complex &m1){ 27 x+=m1.x; 28 y+=m1.y; 29 } 30 31 void output(const Complex &c){ 32 double x=c.get_real(); 33 double y=c.get_imag(); 34 35 std::cout<<x; 36 if(y>=0){ 37 std::cout<<"+"<<y<<"i"; 38 } 39 else{ 40 std::cout<<"-"<<-y<<"i"; 41 } 42 } 43 44 double abs(const Complex &c){ 45 return std::sqrt(c.get_real()*c.get_real()+c.get_imag()*c.get_imag()); 46 } 47 48 Complex add(const Complex &c1,const Complex &c2){ 49 return Complex(c1.get_real()+c2.get_real(),c1.get_imag()+c2.get_imag()); 50 } 51 bool is_equal(const Complex &a,const Complex &b){ 52 return a.get_real()==b.get_real()&&a.get_imag()==b.get_imag(); 53 } 54 bool is_not_equal(const Complex &a,const Complex &b){ 55 return !is_equal(a,b); 56 }
1 #include"Complex.h" 2 #include <iostream> 3 #include <iomanip> 4 #include <complex> 5 void test_Complex(); 6 void test_std_complex(); 7 int main() { 8 std::cout << "*******测试1: 自定义类Complex*******\n"; 9 test_Complex(); 10 std::cout << "\n*******测试2: 标准库模板类complex*******\n"; 11 test_std_complex(); 12 } 13 void test_Complex() { 14 using std::cout; 15 using std::endl; 16 using std::boolalpha; 17 cout << "类成员测试: " << endl; 18 cout << Complex::doc << endl << endl; 19 cout << "Complex对象测试: " << endl; 20 Complex c1; 21 Complex c2(3, -4); 22 Complex c3(c2); 23 Complex c4 = c2; 24 const Complex c5(3.5); 25 cout << "c1 = "; output(c1); cout << endl; 26 cout << "c2 = "; output(c2); cout << endl; 27 cout << "c3 = "; output(c3); cout << endl; 28 cout << "c4 = "; output(c4); cout << endl; 29 cout << "c5.real = " << c5.get_real() 30 << ", c5.imag = " << c5.get_imag() << endl << endl; 31 cout << "复数运算测试: " << endl; 32 cout << "abs(c2) = " << abs(c2) << endl; 33 c1.add(c2); 34 cout << "c1 += c2, c1 = "; output(c1); cout << endl; 35 cout << boolalpha; 36 cout << "c1 == c2 : " << is_equal(c1, c2) << endl; 37 cout << "c1 != c2 : " << is_not_equal(c1, c2) << endl; 38 c4 = add(c2, c3); 39 cout << "c4 = c2 + c3, c4 = "; output(c4); cout << endl; 40 } 41 void test_std_complex() { 42 using std::cout; 43 using std::endl; 44 using std::boolalpha; 45 cout << "std::complex<double>对象测试: " << endl; 46 std::complex<double> c1; 47 std::complex<double> c2(3, -4); 48 std::complex<double> c3(c2); 49 std::complex<double> c4 = c2; 50 const std::complex<double> c5(3.5); 51 cout << "c1 = " << c1 << endl; 52 cout << "c2 = " << c2 << endl; 53 cout << "c3 = " << c3 << endl; 54 cout << "c4 = " << c4 << endl; 55 cout << "c5.real = " << c5.real() 56 << ", c5.imag = " << c5.imag() << endl << endl; 57 cout << "复数运算测试: " << endl; 58 cout << "abs(c2) = " << abs(c2) << endl; 59 c1 += c2; 60 cout << "c1 += c2, c1 = " << c1 << endl; 61 cout << boolalpha; 62 cout << "c1 == c2 : " << (c1 == c2)<< endl; 63 cout << "c1 != c2 : " << (c1 != c2) << endl; 64 c4 = c2 + c3; 65 cout << "c4 = c2 + c3, c4 = " << c4 << endl; 66 }
(2)运行测试截图


(3)回答问题
问题1:标准库模板类complex的使用形式更简洁;函数和运算内在有关联。
问题2:2-1.否。因为output/abs/add等函数都可以通过公有接口get_real()和get_imag()来访问数据。
2-2.否。std::abs(std::complex)是一个独立的模板函数,不是友元函数。
2-3.当需要访问类的私有成员且无法通过公有接口实现时。
问题3:将拷贝构造函数声明为 explicit Complex(const Complex &t);
task3
(1)
1 #pragma once 2 #include <string> 3 4 enum class ControlType {Play, Pause, Next, Prev, Stop, Unknown}; 5 6 class PlayerControl { 7 public: 8 PlayerControl(); 9 10 static int get_cnt(); 11 ControlType parse(const std::string& control_str); // 实现std::string --> ControlType转换 12 void execute(ControlType cmd) const; // 执行控制操作(以打印输出模拟) 13 private: 14 static int total_cnt; 15 };
1 #include "PlayerControl.h" 2 #include <iostream> 3 #include <algorithm> 4 5 int PlayerControl::total_cnt = 0; 6 PlayerControl::PlayerControl() {} 7 // 待补足 8 // 1. 将输入字符串转为小写,实现大小写不敏感 9 // 2. 匹配"play"/"pause"/"next"/"prev"/"stop"并返回对应枚举 10 // 3. 未匹配的字符串返回ControlType::Unknown 11 // 4. 每次成功调用parse时递增total_cnt 12 ControlType PlayerControl::parse(const std::string& control_str) { 13 std::string lower_str; 14 for(auto c:control_str) 15 lower_str+=std::tolower(c); 16 17 ControlType result=ControlType::Unknown; 18 19 if(lower_str=="play") 20 { 21 result=ControlType::Play; 22 } 23 else if(lower_str=="pause") 24 { 25 result=ControlType::Pause; 26 } 27 else if(lower_str=="next") 28 { 29 result=ControlType::Next; 30 } 31 else if(lower_str=="prev") 32 { 33 result=ControlType::Prev; 34 } 35 else if(lower_str=="stop") 36 { 37 result=ControlType::Stop; 38 } 39 40 if(result!=ControlType::Unknown){ 41 total_cnt++; 42 } 43 return result; 44 } 45 void PlayerControl::execute(ControlType cmd) const { 46 switch (cmd) { 47 case ControlType::Play: std::cout << "[play] Playing music...\n"; break; 48 case ControlType::Pause: std::cout << "[Pause] Music paused\n"; break; 49 case ControlType::Next: std::cout << "[Next] Skipping to next track\n"; break; 50 case ControlType::Prev: std::cout << "[Prev] Back to previous track\n"; break; 51 case ControlType::Stop: std::cout << "[Stop] Music stopped\n"; break; 52 default: std::cout << "[Error] unknown control\n"; break; 53 } 54 } 55 int PlayerControl::get_cnt() { 56 return total_cnt; 57 }
1 #include "PlayerControl.h" 2 #include <iostream> 3 void test() 4 { 5 PlayerControl controller; 6 std::string control_str; 7 std::cout << "Enter Control: (play/pause/next/prev/stop/quit):\n"; 8 while(std::cin >> control_str) { 9 if(control_str == "quit") 10 break; 11 12 ControlType cmd = controller.parse(control_str); 13 controller.execute(cmd); 14 std::cout << "Current Player control: " << PlayerControl::get_cnt() << "\n\n"; 15 } 16 } 17 int main() { 18 test(); 19 }
(2)运行测试截图

task4
(1)
1 #pragma once 2 #include<string> 3 4 class Fraction{ 5 public: 6 static const std::string doc; 7 8 private: 9 int up_; 10 int down_; 11 12 void simplify(); 13 static int gcd(int a,int b); 14 15 public: 16 Fraction(int up=0,int down=1); 17 Fraction(const Fraction &t); 18 Fraction(Fraction &&t)=default; 19 ~Fraction()=default; 20 21 Fraction& operator=(const Fraction &c); 22 int get_up()const; 23 int get_down()const; 24 Fraction negative()const; 25 26 }; 27 28 void output(const Fraction &c); 29 Fraction add(const Fraction &c1,const Fraction &c2); 30 Fraction sub(const Fraction &c1,const Fraction &c2); 31 Fraction mul(const Fraction &c1,const Fraction &c2); 32 Fraction div(const Fraction &c1,const Fraction &c2);
1 #include "Fraction.h" 2 #include <iostream> 3 #include <stdexcept> 4 #include <cmath> 5 6 const std::string Fraction::doc = "Fraction类 v 0.01版.\n目前仅支持分数对象的构造、输出、加/减/乘/除运算。"; 7 8 int Fraction::gcd(int a, int b) { 9 a = std::abs(a); 10 b = std::abs(b); 11 while (b != 0) { 12 int temp = b; 13 b = a % b; 14 a = temp; 15 } 16 return a; 17 } 18 19 20 void Fraction::simplify() { 21 if (down_ == 0) { 22 return; 23 } 24 25 26 if (down_ < 0) { 27 up_ = -up_; 28 down_ = -down_; 29 } 30 31 32 int common_divisor = gcd(up_, down_); 33 if (common_divisor != 0) { 34 up_ /= common_divisor; 35 down_ /= common_divisor; 36 } 37 38 39 if (up_ == 0) { 40 down_ = 1; 41 } 42 } 43 44 45 Fraction::Fraction(int up, int down) : up_(up), down_(down) { 46 if (down_ == 0) { 47 48 return; 49 } 50 simplify(); 51 } 52 53 Fraction::Fraction(const Fraction &t) : up_(t.up_), down_(t.down_) {} 54 55 56 Fraction& Fraction::operator=(const Fraction &c) { 57 if (this != &c) { 58 up_ = c.up_; 59 down_ =c.down_; 60 } 61 return *this; 62 } 63 64 65 int Fraction::get_up() const { 66 return up_; 67 } 68 69 int Fraction::get_down() const { 70 return down_; 71 } 72 73 Fraction Fraction::negative() const { 74 return Fraction(-up_, down_); 75 } 76 77 78 void output(const Fraction &c) { 79 if (c.get_down() == 0) { 80 std::cout << "分母不能为0"; 81 return; 82 } 83 84 int up = c.get_up(); 85 int down =c.get_down(); 86 87 if (down == 1) { 88 std::cout << up; 89 } else { 90 std::cout << up << "/" << down; 91 } 92 } 93 94 Fraction add(const Fraction &c1, const Fraction &c2) { 95 int new_up = c1.get_up() * c2.get_down() + c2.get_up() * c1.get_down(); 96 int new_down = c1.get_down() * c2.get_down(); 97 return Fraction(new_up, new_down); 98 } 99 100 Fraction sub(const Fraction &c1, const Fraction &c2) { 101 int new_up = c1.get_up() * c2.get_down() - c2.get_up() * c1.get_down(); 102 int new_down = c1.get_down() * c2.get_down(); 103 return Fraction(new_up, new_down); 104 } 105 106 Fraction mul(const Fraction &c1, const Fraction &c2) { 107 int new_up = c1.get_up() * c2.get_up(); 108 int new_down = c1.get_down() * c2.get_down(); 109 return Fraction(new_up, new_down); 110 } 111 112 Fraction div(const Fraction &c1, const Fraction &c2) { 113 if (c2.get_up() == 0) { 114 return Fraction(1, 0); 115 } 116 int new_up = c1.get_up() * c2.get_down(); 117 int new_down = c1.get_down() * c2.get_up(); 118 return Fraction(new_up, new_down); 119 }
1 #include "Fraction.h" 2 #include <iostream> 3 void test1(); 4 void test2(); 5 int main() { 6 std::cout << "测试1: Fraction类基础功能测试\n"; 7 test1(); 8 std::cout << "\n测试2: 分母为0测试: \n"; 9 test2(); 10 } 11 void test1() { 12 using std::cout; 13 using std::endl; 14 cout << "Fraction类测试: " << endl; 15 cout << Fraction::doc << endl << endl; 16 Fraction f1(5); 17 Fraction f2(3, -4), f3(-18, 12); 18 Fraction f4(f3); 19 cout << "f1 = "; output(f1); cout << endl; 20 cout << "f2 = "; output(f2); cout << endl; 21 cout << "f3 = "; output(f3); cout << endl; 22 cout << "f4 = "; output(f4); cout << endl; 23 24 const Fraction f5(f4.negative()); 25 cout << "f5 = "; output(f5); cout << endl; 26 cout << "f5.get_up() = " << f5.get_up() 27 << ", f5.get_down() = " << f5.get_down() << endl; 28 cout << "f1 + f2 = "; output(add(f1, f2)); cout << endl; 29 cout << "f1 - f2 = "; output(sub(f1, f2)); cout << endl; 30 cout << "f1 * f2 = "; output(mul(f1, f2)); cout << endl; 31 cout << "f1 / f2 = "; output(div(f1, f2)); cout << endl; 32 cout << "f4 + f5 = "; output(add(f4, f5)); cout << endl; 33 } 34 void test2() { 35 using std::cout; 36 using std::endl; 37 Fraction f6(42, 55), f7(0, 3); 38 cout << "f6 = "; output(f6); cout << endl; 39 cout << "f7 = "; output(f7); cout << endl; 40 cout << "f6 / f7 = "; output(div(f6, f7)); cout << endl; 41 }
(2)运行测试截图

(3)回答问题:
问题:自由函数。原因:具有更好的封装性和清晰的接口分离。友元破坏了封装性。静态成员函数不适合这种纯计算。
浙公网安备 33010602011771号