实验2

task 1

T.h

 1 #pragma once
 2 
 3 #include <string>
 4 
 5 class T {
 6 public:
 7     T(int x = 0, int y = 0); 
 8     T(const T& t); 
 9     T(T&& t); 
10     ~T();
11     void adjust(int ratio);
12     void display() const;
13 private:
14     int m1, m2;
15 
16 public:
17     static int get_cnt(); 
18 
19 public:
20     static const std::string doc; 
21     static const int max_cnt; 
22 
23 private:
24     static int cnt; 
25     friend void func();
26 };
27 
28 void func();
T.h

T.cpp

 1 #include "T.h"
 2 #include <iostream>
 3 #include <string>
 4 
 5 const std::string T::doc{ "a simple class sample" };
 6 const int T::max_cnt = 999;
 7 int T::cnt = 0;
 8 
 9 int T::get_cnt() {
10     return cnt;
11 }
12 
13 T::T(int x, int y) : m1{ x }, m2{ y } {
14     ++cnt;
15     std::cout << "T constructor called.\n";
16 }
17 
18 T::T(const T& t) : m1{ t.m1 }, m2{ t.m2 } {
19     ++cnt;
20     std::cout << "T copy constructor called.\n";
21 }
22 
23 T::T(T&& t) : m1{ t.m1 }, m2{ t.m2 } {
24     ++cnt;
25     std::cout << "T move constructor called.\n";
26 }
27 
28 T::~T() {
29     --cnt;
30     std::cout << "T destructor called.\n";
31 }
32 
33 void T::adjust(int ratio) {
34     m1 *= ratio;
35     m2 *= ratio;
36 }
37 
38 void T::display() const {
39     std::cout << "(" << m1 << ", " << m2 << ")";
40 }
41 
42 void func() {
43     T t5(42);
44     t5.m2 = 2049;
45     std::cout << "t5 = "; t5.display(); std::cout << '\n';
46     std::cout << "func: T objects'current count: " << T::get_cnt() << std::endl;
47 }
T.cpp

task 1.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     std::cout << "\ntest friend func: \n";
10     func();
11 }
12 
13 void test_T() {
14     using std::cout;
15     using std::endl;
16 
17     cout << "T info: " << T::doc << endl;
18     cout << "T objects'max count: " << T::max_cnt << endl;
19     cout << "T objects'current count: " << T::get_cnt() << endl << endl;
20 
21     T t1;
22     cout << "t1 = "; t1.display(); cout << endl;
23 
24     T t2(3, 4);
25     cout << "t2 = "; t2.display(); cout << endl;
26 
27     T t3(t2);
28     t3.adjust(2);
29     cout << "t3 = "; t3.display(); cout << endl;
30 
31     T t4(std::move(t2));
32     cout << "t4 = "; t4.display(); cout << endl;
33 
34     cout << "test: T objects'current count: " << T::get_cnt() << endl;
35 }
task 1.cpp

image

 Q1:

image

 friend 只声明了func是T类的友元,并没有定义func这个函数,所以在主函数里找不到标识符func

 

Q2:

T(int x=0,int y=0):普通构造函数

功能:初始化类的对象,为成员变量分配内存并赋予初始值(若没填写参数则默认为0)

调用时机:创建类的对象时调用

T(const T &t):复制构造函数

功能:用已经存在的类对象初始化新的类对象(深拷贝)

调用时机:用已有的对象初始化新的对象时调用,T t2{t1}

T(T &&t):移动构造函数

功能:将临时对象用右值引用的方式移动到新对象中

调用时机:用右值初始化新对象时调用,T t2=std::move(t1)

~T():析构函数

功能:释放类的对象占用内存

调用时机:类对象生命周期结束时调用

 

Q3:

image

 静态成员变量的定义需在类外且仅定义一次,若将定义放在头文件中,头文件被多个源文件包含时会导致重复定义

 

task 2

Complex.h

 

 1 #pragma once
 2 
 3 #include<string>
 4 
 5 class Complex
 6 {
 7 public:
 8     Complex(double a = 0, double b = 0);
 9     Complex(const Complex& c);
10     ~Complex();
11 
12     double get_real() const;
13     double get_imag() const;
14     void add(const Complex& c);
15 
16     static const std::string doc;
17 
18 private:
19     double real, imag;
20 
21 public:
22     friend void output(const Complex &c);
23     friend double abs(const Complex &c);
24     friend Complex add(const Complex& c1,const Complex& c2);
25     friend bool is_equal(const Complex& c1,const Complex& c2);
26     friend bool is_not_equal(const Complex& c1,const Complex& c2);
27 };
28 
29 void output(const Complex& c);
30 double abs(const Complex& c);
31 Complex add(const Complex& c1, const Complex& c2);
32 bool is_equal(const Complex& c1, const Complex& c2);
33 bool is_not_equal(const Complex& c1, const Complex& c2);

 

Complex.cpp

 1 #include "Complex.h"
 2 #include<iostream>
 3 #include<string>
 4 #include<cmath>
 5 
 6 const std::string Complex::doc{ "a simplified complex class" };
 7 
 8 Complex::Complex(double a, double b) :real{ a }, imag{ b } {}
 9 Complex::Complex(const Complex &c):real{c.real},imag{c.imag}{}
10 Complex::~Complex(){}
11 
12 double Complex::get_real() const {
13     return real;
14 }
15 
16 double Complex::get_imag() const {
17     return imag;
18 }
19 
20 void Complex::add(const Complex & c) {
21     real += c.real;
22     imag += c.imag;
23 }
24 
25 void output(const Complex& c) {
26     std::cout << c.real;
27 
28     if (c.imag >= 0)
29         std::cout << " + ";
30     else
31         std::cout << " - ";
32 
33     std::cout << std::abs(c.imag) << "i";
34 }
35 
36 double abs(const Complex& c) {
37     return std::sqrt(c.real * c.real + c.imag * c.imag);
38 }
39 
40 Complex add(const Complex& c1, const Complex& c2) {
41     double real = c1.real + c2.real;
42     double imag = c1.imag + c2.imag;
43 
44     return Complex(real, imag);
45 }
46 
47 bool is_equal(const Complex& c1, const Complex& c2) {
48     if (c1.real == c2.real && c1.imag == c2.imag)
49         return true;
50     else
51         return false;
52 }
53 
54 bool is_not_equal(const Complex& c1, const Complex& c2) {
55     if (c1.real != c2.real || c1.imag != c2.imag)
56         return true;
57     else
58         return false;
59 }

task 2.cpp

 1 #include"Complex.h"
 2 
 3 #include <iostream>
 4 #include <iomanip>
 5 #include <complex>
 6 
 7 void test_Complex();
 8 void test_std_complex();
 9 
10 int main() {
11     std::cout << "*******测试1: 自定义类Complex*******\n";
12     test_Complex();
13 
14     std::cout << "\n*******测试2: 标准库模板类complex*******\n";
15     test_std_complex();
16 }
17 
18 void test_Complex() {
19     using std::cout;
20     using std::endl;
21     using std::boolalpha;
22 
23     cout << "类成员测试: " << endl;
24     cout << Complex::doc << endl << endl;
25 
26     cout << "Complex对象测试: " << endl;
27     Complex c1;
28     Complex c2(3, -4);
29     Complex c3(c2);
30     Complex c4 = c2;
31     const Complex c5(3.5);
32 
33     cout << "c1 = "; output(c1); cout << endl;
34     cout << "c2 = "; output(c2); cout << endl;
35     cout << "c3 = "; output(c3); cout << endl;
36     cout << "c4 = "; output(c4); cout << endl;
37     cout << "c5.real = " << c5.get_real()
38         << ", c5.imag = " << c5.get_imag() << endl << endl;
39 
40     cout << "复数运算测试: " << endl;
41     cout << "abs(c2) = " << abs(c2) << endl;
42     c1.add(c2);
43     cout << "c1 += c2, c1 = "; output(c1); cout << endl;
44     cout << boolalpha;
45     cout << "c1 == c2 : " << is_equal(c1, c2) << endl;
46     cout << "c1 != c2 : " << is_not_equal(c1, c2) << endl;
47     c4 = add(c2, c3);
48     cout << "c4 = c2 + c3, c4 = "; output(c4); cout << endl;
49 }
50 void test_std_complex() {
51     using std::cout;
52     using std::endl;
53     using std::boolalpha;
54 
55     cout << "std::complex<double>对象测试: " << endl;
56     std::complex<double> c1;
57     std::complex<double> c2(3, -4);
58     std::complex<double> c3(c2);
59     std::complex<double> c4 = c2;
60     const std::complex<double> c5(3.5);
61 
62     cout << "c1 = " << c1 << endl;
63     cout << "c2 = " << c2 << endl;
64     cout << "c3 = " << c3 << endl;
65     cout << "c4 = " << c4 << endl;
66 
67     cout << "c5.real = " << c5.real()
68         << ", c5.imag = " << c5.imag() << endl << endl;
69 
70     cout << "复数运算测试: " << endl;
71     cout << "abs(c2) = " << abs(c2) << endl;
72     c1 += c2;
73     cout << "c1 += c2, c1 = " << c1 << endl;
74     cout << boolalpha;
75     cout << "c1 == c2 : " << (c1 == c2) << endl;
76     cout << "c1 != c2 : " << (c1 != c2) << endl;
77     c4 = c2 + c3;
78     cout << "c4 = c2 + c3, c4 = " << c4 << endl;
79 }
task 2.cpp

image

 Q1:在使用形式上,标准库模板类complex更简洁,函数和运算内在有关联

Q2-1:是。output输出要用到real和imag;abs取模要用到real和imag的运算;add要用real和imag来进行虚部和实部的相加运算,real和imag是私有数据

Q2-2:否。

Q2-3:当外部函数必须要直接用到类内部的私有数据时要用到friend

Q3:在public中添加Complex &operator=(const Complex)=delete;

 

task 3

PlayerControl.h

 1 #pragma once
 2 #include<string>
 3 
 4 enum class ControlType { Play, Pause, Next, Prev, Stop, Unknown };
 5 
 6 class PlayerControl
 7 {
 8 public:
 9     PlayerControl();
10     ControlType parse(const std::string& control_str); 
11     void execute(ControlType cmd) const; 
12 
13     static int get_cnt();
14 
15 private:
16     static int total_cnt;
17 };
PlayerControl.h

PlayerControl.cpp

 1 #include "PlayerControl.h"
 2 #include <iostream>
 3 #include <algorithm>
 4 
 5 int PlayerControl::total_cnt = 0;
 6 
 7 PlayerControl::PlayerControl() {}
 8 
 9 ControlType PlayerControl::parse(const std::string& control_str) {
10     std::string ans;
11     ans.reserve(control_str.size());
12 
13     for (unsigned char ch : control_str) 
14         ans += std::tolower(ch);
15 
16     if (ans == "play") {
17         total_cnt++;
18         return ControlType::Play;
19     }
20     else if (ans == "pause") {
21         total_cnt++;
22         return ControlType::Pause;
23     }
24     else if (ans == "next") {
25         total_cnt++;
26         return ControlType::Next;
27     }
28     else if (ans == "prev") {
29         total_cnt++;
30         return ControlType::Prev;
31     }
32     else if (ans == "stop") {
33         total_cnt++;
34         return ControlType::Stop;
35     }
36     else {
37         total_cnt++;
38         return ControlType::Unknown;
39     }
40 }
41 
42 void PlayerControl::execute(ControlType cmd) const {
43     switch (cmd) {
44     case ControlType::Play: std::cout << "[play] Playing music...\n"; break;
45     case ControlType::Pause: std::cout << "[Pause] Music paused\n"; break;
46     case ControlType::Next: std::cout << "[Next] Skipping to next track\n"; break;
47     case ControlType::Prev: std::cout << "[Prev] Back to previous track\n"; break;
48     case ControlType::Stop: std::cout << "[Stop] Music stopped\n"; break;
49     default: std::cout << "[Error] unknown control\n"; break;
50     }
51 }
52 
53 int PlayerControl::get_cnt() {
54     return total_cnt;
55 }

task 3.cpp

 1 #include "PlayerControl.h"
 2 #include <iostream>
 3 void test() {
 4     PlayerControl controller;
 5     std::string control_str;
 6     std::cout << "Enter Control: (play/pause/next/prev/stop/quit):\n";
 7     while (std::cin >> control_str) {
 8         if (control_str == "quit")
 9             break;
10         ControlType cmd = controller.parse(control_str);
11         controller.execute(cmd);
12         std::cout << "Current Player control: " << PlayerControl::get_cnt() << "\n\n";
13     }
14 }
15 
16 int main() {
17     test();
18 }
task 3.cpp

 

image

 

task 4

 Fraction.h

 1 #pragma once
 2 #include<string>
 3 
 4 class Fraction
 5 {
 6 public:
 7     Fraction(int UP, int DOWN = 1);
 8     Fraction(const Fraction& f);
 9     ~Fraction();
10 
11     int get_up() const;
12     int get_down() const;
13     Fraction negative();
14 
15     static const std::string doc;
16 
17 private:
18     int up, down;
19 
20 public:
21     friend void output(const Fraction& f);
22     friend Fraction add(const Fraction& f1, const Fraction& f2);
23     friend Fraction sub(const Fraction& f1, const Fraction& f2);
24     friend Fraction mul(const Fraction& f1, const Fraction& f2);
25     friend Fraction div(const Fraction& f1, const Fraction& f2);
26 };
27 
28 void output(const Fraction& f);
29 Fraction add(const Fraction& f1, const Fraction& f2);
30 Fraction sub(const Fraction& f1, const Fraction& f2);
31 Fraction mul(const Fraction& f1, const Fraction& f2);
32 Fraction div(const Fraction& f1, const Fraction& f2);

Fraction.cpp

  1 #include "Fraction.h"
  2 #include<iostream>
  3 #include<cmath>
  4 #include <utility>
  5 
  6 int gcd(int a, int b);
  7 int lcm(int a, int b);
  8 
  9 const std::string Fraction::doc{ "Fraction类v 0.01版\n目前仅支持分数对象的构造、输出、加/减/乘/除运算" };
 10 
 11 Fraction::Fraction(int UP, int DOWN) :up{ UP }, down{ DOWN }{}
 12 Fraction::Fraction(const Fraction& f) :up{ f.up }, down{ f.down }{}
 13 Fraction::~Fraction(){}
 14 
 15 int Fraction::get_up() const {
 16     int new_up = up / gcd(up, down);
 17     return new_up;
 18 }
 19 
 20 int Fraction::get_down() const {
 21     int new_down = down / gcd(up, down);
 22     return new_down;
 23 }
 24 
 25 Fraction Fraction::negative() {
 26     int a = 0 - up;
 27     return Fraction(a, down);
 28 }
 29 
 30 void output(const Fraction& f) {
 31     if (f.down == 0) return;
 32     if (f.up == 0) {
 33         std::cout << 0;
 34         return;
 35     }
 36 
 37     int t = gcd(f.up, f.down);
 38     int new_up = f.up / t;
 39     int new_down = f.down / t;
 40 
 41     if (new_down == 1)
 42         std::cout << std::abs(new_up);
 43     else {
 44         if ((new_up > 0 && new_down > 0) || (new_up < 0 && new_down < 0))
 45             std::cout << std::abs(new_up) << "/" << std::abs(new_down);
 46         else
 47             std::cout << "-" << std::abs(new_up) << "/" << std::abs(new_down);
 48     }
 49 }
 50 
 51 Fraction add(const Fraction& f1,const Fraction& f2){
 52     if (f1.down == f2.down)
 53         return Fraction(f1.up + f2.up, f1.down);
 54     else {
 55         int t = lcm(f1.down, f2.down);
 56         return Fraction(f1.up * (t / f1.down) + f2.up * (t / f2.down), t);
 57     }
 58 }
 59 
 60 Fraction sub(const Fraction& f1, const Fraction& f2) {
 61     if (f1.down == f2.down)
 62         return Fraction(f1.up - f2.up, f1.down);
 63     else {
 64         int t = lcm(f1.down, f2.down);
 65         return Fraction(f1.up * (t / f1.down) - f2.up * (t / f2.down), t);
 66     }
 67 }
 68 
 69 Fraction mul(const Fraction& f1, const Fraction& f2) {
 70     if (f1.up == 0 || f2.up == 0)
 71         return Fraction(0);
 72     else {
 73         return Fraction(f1.up * f2.up, f1.down * f2.down);
 74     }
 75 }
 76 
 77 Fraction div(const Fraction& f1, const Fraction& f2) {
 78     if (f2.up == 0) {
 79         std::cout << "分母不能为0";
 80         return Fraction(0, 0);
 81     }
 82     else if (f1.up == 0)
 83         return Fraction(0);
 84     else
 85         return Fraction(f1.up * f2.down, f2.up * f1.down);
 86 }
 87 
 88 int gcd(int a, int b) {
 89     int new_a = std::abs(a);
 90     int new_b = std::abs(b);
 91 
 92     if (new_a < new_b)
 93         std::swap(new_a, new_b);
 94 
 95     while (new_b != 0) {
 96         int t = new_b;
 97         new_b = new_a % new_b;
 98         new_a = t;
 99     }
100     return new_a;
101 }
102 
103 int lcm(int a, int b) {
104     return(std::abs(a) / gcd(a, b) * std::abs(b));
105 }

task 4.cpp

 1 #include"Fraction.h"
 2 #include<iostream>
 3 
 4 void test1();
 5 void test2();
 6 
 7 int main() {
 8     std::cout << "测试1: Fraction类基础功能测试\n";
 9     test1();
10     std::cout << "\n测试2: 分母为0测试: \n";
11     test2();
12 }
13 void test1() {
14     using std::cout;
15     using std::endl;
16 
17     cout << "Fraction类测试: " << endl;
18     cout << Fraction::doc << endl << endl;
19 
20     Fraction f1(5);
21     Fraction f2(3, -4), f3(-18, 12);
22     Fraction f4(f3);
23     cout << "f1 = "; output(f1); cout << endl;
24     cout << "f2 = "; output(f2); cout << endl;
25     cout << "f3 = "; output(f3); cout << endl;
26     cout << "f4 = "; output(f4); cout << endl;
27 
28     const Fraction f5(f4.negative());
29     cout << "f5 = "; output(f5); cout << endl;
30     cout << "f5.get_up() = " << f5.get_up()
31         << ", f5.get_down() = " << f5.get_down() << endl;
32 
33     cout << "f1 + f2 = "; output(add(f1, f2)); cout << endl;
34     cout << "f1 - f2 = "; output(sub(f1, f2)); cout << endl;
35     cout << "f1 * f2 = "; output(mul(f1, f2)); cout << endl;
36     cout << "f1 / f2 = "; output(div(f1, f2)); cout << endl;
37     cout << "f4 + f5 = "; output(add(f4, f5)); cout << endl;
38 }
39 void test2() {
40     using std::cout;
41     using std::endl;
42 
43     Fraction f6(42, 55), f7(0, 3);
44     cout << "f6 = "; output(f6); cout << endl;
45     cout << "f7 = "; output(f7); cout << endl;
46     cout << "f6 / f7 = "; output(div(f6, f7)); cout << endl;
47 }
task 4.cpp

image

 

Q:我选择了友元。

优点:友元可以直接访问类的私有成员,分数的加减乘除都要用到这些私有成员,简化代码逻辑;接口清晰明了

缺点:破坏了类的封装性

posted @ 2025-10-27 12:55  璐Luzi  阅读(4)  评论(0)    收藏  举报