实验二

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();
T.h
 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 }
T.cpp
 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 }
task.cpp

(2)运行结果截图

image

 (3)问题一:

image

原因: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);
Complex.h
 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 }
Complex.cpp
 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  }
task2.cpp

(2)运行测试截图

image

image

 (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 };
PlayerContral.h
 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  }
PlayerContral.cpp
 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  }
task3.cpp

(2)运行测试截图

image

 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);
Fraction.h
  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 }
Fraction.cpp
 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  }
task4.cpp

(2)运行测试截图

image

 (3)回答问题:

问题:自由函数。原因:具有更好的封装性和清晰的接口分离。友元破坏了封装性。静态成员函数不适合这种纯计算。

posted @ 2025-10-29 00:31  deep_l  阅读(7)  评论(1)    收藏  举报