实验2 类和对象——基础编程1

一、实验目的

 加深对类,对象的理解,能够解释类的封装,类的接口

会使用C++语法规则正确定义,实现,测试类,会使用类创建对象,并基于对象编程

针对具体问题场景,练习运用面向对象思维进行设计,合理利用C++语言特性(访问权限控制,static,friend,const),在数据共享和保护之间达到平衡

会用多文件方式组织代码

加深对C++内存资源管理技术的理解,能够解释构造函数,析构函数的用途,分析它们何时会被调用

二、实验准备

 类的抽象,设计

使用C++定义类,使用类创建对象的语法;构造/析构陈洁灵语法,用途及调用时机

类的共享与保护机制:访问权限控制,静态成员(static),友元(friend),const

多文件组织代码

 

三、实验内容

 

1. 实验任务1

代码:

 t.h

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

t.cpp

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

task1.cpp

 1 #include"t.h"
 2 #include<iostream>
 3 
 4 using std::cout;
 5 using std::endl;
 6 
 7 void test ( );
 8 
 9 int main()
10 {
11     test();
12     cout<<"\nmain:\n";
13     cout<<"T objects'current count:"<<T::get_cnt()<<endl;
14     
15 }
16 
17 void test()
18 {
19     cout<<"test class T:\n";
20     cout<<"T info:"<<T::doc<<endl;
21     cout<<"T objects'max count: "<<T::max_cnt<<endl;
22     cout<<"T objects'current count: "<<T::get_cnt()<<endl<<endl;
23     
24     T t1;
25     cout<<"t1 = ";t1.display();cout<<endl;
26     
27     T t2(3,4);
28     cout <<"t2 = ";t2.display();cout<<endl;
29     
30     T t3(t2);
31     t3.adjust(2);
32     cout<<"t3 = ";t3.display();cout<<endl;
33     
34     T t4(std::move(t2));
35     cout<<"t3 = ";t4.display();cout<<endl;
36     
37     cout<<"T objects'current count: "<<T::get_cnt()<<endl;
38     func();
39 }

 

 

运行截图:

 

 

 

问题回答:

 

问题一:不可以去掉t.h中最后的void func();

friend void func()不可以作为一个完整的函数声明。没有给出函数的参数列表。故还是需要在在t.h最后加上void func();

问题二:构造函数是在对象被创建时利用特定的值构造对象,将对象初始化为一个特定的状态。

普通构造函数是创建一个对象假如有两个参数,就可以接受两个参数,如果没有参数就是使用自定义的默认值,可以是0或者其它。

复制构造函数是一个已经存在的对象创建新的对象的时候调用它,新对象与存在的对象状态相同。

移动构造函数它通过右值引用来实现资源的转移。

调用时机:调用构造函数结束后调用析构函数,析构的顺序与构造的顺序相反。

 

 问题三:

不能正确编译运行

 

2. 实验任务2

代码:

Complex.h

 1 #pragma once
 2 #include<string>
 3 
 4 class Complex{
 5     //类属性 
 6     public:
 7         static const std::string doc;
 8         Complex(double a=0,double b=0);
 9         Complex(const Complex &c);
10         
11     
12     //对象属性
13     private:
14         double real;
15         double imag;
16     //对象方法
17     public:
18          //接口:
19            const double get_real();
20            const double get_imag();
21            Complex add(const Complex& c);
22     //友元函数
23     public:
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         friend void output(const Complex &c);
28         friend double abs(const Complex &c);
29          ~Complex();
30 };
31 
32  Complex add(const Complex &c1,const Complex &c2);
33  bool is_equal(const Complex &c1,const Complex &c2);
34  bool is_not_equal(const Complex &c1,const Complex &c2);
35  void output(const Complex &c);
36  double abs(const Complex &c);

Complex.cpp

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

 

 

运行截图:

 

 

 

 

 

 

 

3. 实验任务3

代码:

 

 1 #include <iostream>
 2 #include <complex>
 3 
 4 using std::cout;
 5 using std::endl;
 6 using std::boolalpha;
 7 using std::complex;
 8 
 9 void test() {
10     cout << "标准库模板类comple测试: " << endl;
11     complex<double> c1;
12     complex<double> c2(3, -4);
13     const complex<double> c3(3.5);
14     complex<double> c4(c3);
15 
16     cout << "c1 = " << c1 << endl;
17     cout << "c2 = " << c2 << endl;
18     cout << "c3 = " << c3 << endl;
19     cout << "c4 = " << c4 << endl;
20     cout << "c4.real = " << c4.real() << ", c4.imag = " << c4.imag() << endl;
21     cout << endl;
22 
23     cout << "复数运算测试: " << endl;
24     cout << "abs(c2) = " << abs(c2) << endl;
25     c1 += c2;
26     cout << "c1 += c2, c1 = " << c1 << endl;
27     cout << boolalpha;
28     cout << "c1 == c2 : " << (c1 == c2) << endl;
29     cout << "c1 != c3 : " << (c1 != c3) << endl;
30     c4 = c2 + c3;
31     cout << "c4 = c2 + c3, c4 = " << c4 << endl;
32 }
33 
34 int main() {
35     test();
36 }

 

 

运行截图:

 

 

 

 问题回答:

 

 

 

4. 实验任务4

代码:

Fraction.h

 1 #pragma once
 2 #include<string>
 3 
 4 class Fraction{
 5     public:
 6         static const std::string doc;
 7         Fraction(int up=1,int down=1);
 8         Fraction(const Fraction &c);
 9         
10     int get_up()const;
11     int get_down() const ;
12     Fraction negative() const;
13     static int gcd(int a,int b);
14     Fraction simplify()const;
15         
16     public:    
17     //友元函数
18         friend void output(const Fraction &c);
19         friend Fraction add(const Fraction &c1,const Fraction &c2);
20         friend Fraction sub(const Fraction &c1,const Fraction &c2);
21         friend Fraction mul(const Fraction &c1,const Fraction &c2);
22         friend Fraction div(const Fraction &c1,const Fraction &c2);
23         ~Fraction();
24     private:
25         int up;
26         int down;
27         
28          
29 };

Fraction.cpp

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

 

 Fraction_test.cpp

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

 

 

运行截图:

 

 

 

 

 

 

 

5. 实验任务5

代码:

Bank.h

 1 #ifndef ACCOUNT_H
 2 #define ACCOUNT_H
 3 
 4 class SavingsAccount{
 5     private://用户的Id ,平均数,利率,上次存款时间,计算,总和这些数是私有的。 
 6         int id;
 7         double balance;
 8         double rate;
 9         int lastDate;
10         double accumulation;
11         static double total;
12         void record(int data,double amount);//一个成员函数:用于输出 
13         double accumulate(int date)const{return accumulation+balance*(date-lastDate);}
14     public:
15     SavingsAccount(int date,int id,double rate);
16     int getId()const{return id;    }
17     double getBalance ()const {return balance;}
18     double getRate()const{return rate;}
19     static double getTotal(){return total;
20     }
21     void deposit(int date,double amount);//
22     void withdraw(int date,double amount);//
23     void settle(int date);//结算 
24     void show()const;
25 };
26 #endif 

Bank.cpp

 1 #include <iostream>
 2 #include "bank.h"
 3 #include <cmath>
 4 
 5 using namespace std;
 6  
 7 double SavingsAccount::total = 0;
 8 
 9 SavingsAccount::SavingsAccount(int date, int id, double rate): id(id), balance(0), rate(rate), lastDate(date), accumulation(0) {
10      std::cout << date << "\t#" << id << " is created" << std::endl;
11  }
12 void SavingsAccount::record(int date, double amount) {
13 accumulation = accumulate(date);
14 lastDate = date;
15 amount = floor(amount * 100 + 0.5) / 100;     //保留小数点后两位
16 balance += amount;
17 total += amount;
18 std::cout << date << "\t#" << id << "\t" << amount << "\t"<< balance << std::endl;
19 }
20  void SavingsAccount::deposit(int date, double amount) {
21 record(date, amount);
22 }
23 void SavingsAccount::withdraw(int date, double amount) {
24 if (amount > getBalance()) {
25 std::cout << "Error: not enough money" << std::endl;
26 }
27 else {
28 record(date, -amount);
29 }
30 }
31 void SavingsAccount::settle(int date) {
32 double interest = accumulate(date) * rate / 365;        //计算年息
33 if (interest != 0) 
34 record(date, interest);
35 accumulation = 0;
36 }
37 void SavingsAccount::show() const {
38 std::cout << "#" << id << "\tBalance: " << balance;
39 }

Bank_test.cpp

 1 #include "bank.h"
 2 #include <iostream>
 3 using namespace std;
 4 int main() {
 5 
 6 SavingsAccount sa0(1, 21325302, 0.015);
 7 SavingsAccount sal(1, 58320212, 0.015);
 8 
 9 sa0.deposit(5, 5000);
10 sal.deposit(25, 10000);
11 sa0.deposit(45, 5500);
12 sal.withdraw(60, 4000);
13 
14 sa0.settle(90);
15 sal.settle(90);
16 
17 sa0.show();
18 cout << endl;
19 sal.show();
20 cout << endl;
21  cout << "Total: " << SavingsAccount::getTotal() << endl;
22  return 0;
23 }

 

 

 

运行截图:

 

 

 个人银行账户管理系统使用了SavingsAccout()类封装了相关类的属性以及方法。也有不到位的地方,比如输入日期,钱数,取款数这些数据,要设置确保数据的输入是合理的,部分不能为负数。

 

posted @ 2024-10-27 09:26  安东尼23  阅读(10)  评论(0编辑  收藏  举报