首页 > 编程语言 >实验2 类和对象_基础编程1

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

时间:2024-10-29 16:46:57浏览次数:6  
标签:std const 对象 编程 int Complex 实验 Fraction include

任务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     
12     void adjust(int ratio);
13     void display() const;
14 
15 private:
16     int m1,m2;
17     
18 public:
19     static int get_cnt();
20     
21 public:
22     static const std::string doc;
23     static const int max_cnt;
24     
25 private:
26     static int cnt;
27     
28     friend void func();
29 };
30 
31 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 
13 T::T(int x,int y): m1{x},m2{y} {
14     ++cnt;
15      cout<<"T constructor called.\n";
16 }
17 
18 T::T(const T &t): m1{t.m1},m2{t.m2} {
19     ++cnt;
20     cout<<"T copy constructor called.\n";
21 }
22 
23 T::T(T &&t): m1{t.m1},m2{t.m2} {
24     ++cnt;
25     cout<<"T move constructor called.\n";
26 }
27 
28 T::~T() {
29     --cnt;
30     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     cout<<"("<<m1<<","<<m2<<")";
40 }
41 
42 int T::get_cnt() {
43     return cnt;
44 }
45 
46 void func() {
47     T t5(42);
48     t5.m2 = 2049;
49     cout<<"t5 = "; t5.display(); cout<<endl;
50 }

 

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     test();
11     cout<<"\nmain: \n";
12     cout<<"T objects'current count: "<<T::get_cnt()<<endl;
13 }
14 
15 void test() {
16     cout<<"test class T: \n";
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<<"t3 = "; t4.display(); cout<<endl; 
33     
34     cout<<"T objects'current count: "<<T::get_cnt()<<endl;
35     
36     func(); 
37 }

 

问题1:

不能正确运行

截图:

可能原因:

在 C++ 中,必须在类头文件中的友元函数声明和在全局作用域中的函数声明之间理解作用域和可见性之间的差异。当在类中使用 friend声明一个函数(如 friend void func();),是在通知编译器这个函数是友元函数,因而能够访问该类的私有和保护成员。但这只提供了友元访问的能力。如果没有在全局作用域中声明函数,编译器在调用它时仍然不知道函数的原型,如果想要从类外部的其他地方调用该函数,需要在全局作用域中给出该函数的声明,以便编译器知道函数的参数和返回值类型。

在代码中,friend void func(); 声明了func 是一个友元函数,并允许这个函数访问类 X 的私有成员。然而,真正的函数原型 void func();仍然需要在全局作用域中明确声明,以便保证 func 在该作用域内可用,确保在其他源文件中调用这个函数时不会遇到链接错误。

 

问题2:

默认构造函数 (T(int x =0, int y =0))

功能:为类 T 创建对象时提供默认值。如果没有提供参数,则 x 和 y 被初始化为 0。此构造函数用于允许不带参数创建对象。

调用时机:当使用默认构造形式创建对象时,如 T t1; 或 T t2(3,4); 。

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

功能:通过转移(移动)另一个对象 t 的资源来初始化新对象,优化性能并减少内存的浪费。在移动构造中,原对象 t 的状态会被重置,防止其析构时意外释放资源。

调用时机:在使用 std::move 或在某些情况下如返回值优化时创建对象时,例如:T t4(std::move(t2)); 。

析构函数析构函数 (~T())

功能:用于清理对象在生命周期内分配的资源,负责释放动态分配的内存、关闭打开的文件、释放网络连接等。

调用时机:当对象的作用域结束或对象被显式删除时(例如:当一个方法结束、局部对象超出作用域时或通过 delete关键字释放对象时)。

 

问题3:

不能,所有的静态成员变量(包括静态常量和静态计数器)都应在一个源文件中定义和初始化,即上面的 t.cpp。

 

运行成功截图:

 

任务2:

Complex.h

 1 #include<iostream>
 2 #include<string>
 3 
 4 class Complex{
 5 public:
 6     Complex(double r=0.0,double i=0.0);
 7     Complex(const Complex &c);
 8     
 9     double get_real() const;
10     double get_imag() const;
11     void add(const Complex& c);
12 
13 private:
14     double real;
15     double imag;
16     
17 public:
18     static const std::string doc;
19         
20     friend Complex add(const Complex& c1,const Complex& c2);
21     friend bool is_equal(const Complex& c1,const Complex& c2);
22     friend bool is_not_equal(const Complex& c1,const Complex& c2);
23     friend double abs(const Complex& c);
24     friend void output(const Complex& c);
25     
26 }; 

 

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 r,double i): real{r},imag{i} {}
 9 
10 Complex::Complex(const Complex &c): real{c.real},imag{c.imag} {}
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 Complex add(const Complex& c1,const Complex& c2) {
26      return Complex(c1.real + c2.real, c1.imag + c2.imag);
27 }
28 
29 bool is_equal(const Complex& c1,const Complex& c2) {
30     if(c1.real==c2.real&&c1.imag==c2.imag)
31     return true;
32     else
33     return false;
34 }
35 
36 bool is_not_equal(const Complex& c1,const Complex& c2) {
37     if((c1.real!=c2.real||c1.imag!=c2.imag))
38     return true;
39     else
40     return false;
41 }
42 
43 double abs(const Complex& c) {
44     return sqrt(c.real*c.real+c.imag*c.imag);
45 }
46 
47 void output(const Complex& c) {
48     std::cout<<c.real;
49     if(c.imag>=0)
50     std::cout<<" + ";
51     std::cout<<c.imag<<"i";
52 }

 

task2.cpp
 1 #include "Complex.h"
 2 #include <iostream>
 3 
 4 using std::cout;
 5 using std::endl;
 6 using std::boolalpha;
 7 
 8 void test() {
 9     cout << "类成员测试: " << endl;
10     cout << Complex::doc << endl;
11 
12     cout << endl;
13 
14     cout << "Complex对象测试: " << endl;
15     Complex c1;
16     Complex c2(3, -4);
17     const Complex c3(3.5);
18     Complex c4(c3);
19 
20     cout << "c1 = "; output(c1); cout << endl;
21     cout << "c2 = "; output(c2); cout << endl;
22     cout << "c3 = "; output(c3); cout << endl;
23     cout << "c4 = "; output(c4); cout << endl;
24     cout << "c4.real = " << c4.get_real() << ", c4.imag = " << c4.get_imag() << endl;
25 
26     cout << endl;
27 
28     cout << "复数运算测试: " << endl;
29     cout << "abs(c2) = " << abs(c2) << endl;
30     c1.add(c2);
31     cout << "c1 += c2, c1 = "; output(c1); cout << endl;
32     cout << boolalpha;
33     cout << "c1 == c2 : " << is_equal(c1, c2) << endl;
34     cout << "c1 != c3 : " << is_not_equal(c1, c3) << endl;
35     c4 = add(c2, c3);
36     cout << "c4 = c2 + c3, c4 = "; output(c4); cout << endl;
37 }
38 
39 int main() {
40     test();
41 }

 

运行成功截图:

 

任务3:

task3.cpp

 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<<"标准库模板类complex测试:"<<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!=c4)<<endl;
30     c4=c2+c3;
31     cout<<"c4 = c2 + c3, c4 = "<<c4<<endl;    
32 }
33 
34 int main() {
35     test();
36 }

 

运行结果截图:

 

对比任务2:

1.对比差异

比较判断两个复数是否相同,标准库中的接口为 (c1==c2) 和 (c1!=c4) 取代了 is_equal(c1, c2) 和 is_not_equal(c1, c3)

将另一个复数加到一复数上,标准库中的接口为c1+=c2;取代了实验二中的c1.add(c2)

标准库中输出直接为cout<<c1;取代了实验二中的output()函数

求两复数之和 c4=c2+c3 取代了 c4 = add(c2, c3); 2.启发 标准库的接口如 c4 = c2 + c3使得复数的加法更符合直观的数学表达,提升了可读性。而自定义实现的 add(c2, c3) 则显得不够自然。

标准库允许通过 std::cout << c1直接输出复数,而自定义实现的 output() 方法,降低了代码的可读性和灵活性。

标准库通过运算符重载(如 c1 == c2 和 c1 != c2)使得复数相等比较的语法更为简便直观,而自定义实现使用函数调用(如 is_equal(c1, c2))显得冗长。

设计时应追求简洁、高效的接口,尽量减少冗长的函数调用,提升代码流畅性。   任务4: Fraction.h
 1 #pragma once
 2 #include<iostream>
 3 
 4 class Fraction{
 5 public:
 6     Fraction(int up, int down=1);
 7     Fraction(const Fraction &f);
 8     
 9     int get_up() const;
10     int get_down() const;
11     Fraction negative() const;
12     void simplify();
13     int gcd(int a,int b);
14     
15     static const std::string doc;
16 private:
17     int up,down;    
18         
19     friend void output(const Fraction& f1);
20     friend Fraction add(const Fraction& f1,const Fraction& f2);
21     friend Fraction sub(const Fraction& f1,const Fraction& f2);
22     friend Fraction mul(const Fraction& f1,const Fraction& f2);
23     friend Fraction div(const Fraction& f1,const Fraction& f2);
24 };
25 
26 void output(const Fraction &f);
27 Fraction add(const Fraction &f1,const Fraction &f2);
28 Fraction sub(const Fraction &f1,const Fraction &f2);
29 Fraction mul(const Fraction &f1,const Fraction &f2);
30 Fraction div(const Fraction &f1,const Fraction &f2);

 

Fraction.cpp
 1 #include"Fraction.h"
 2 #include<string>
 3 #include<iostream>
 4 
 5 using namespace std;
 6 
 7 const string Fraction::doc{"Fraction类 v 0.01版.\n目前仅支持分数对象的构造、输出、加/减/乘/除运算."};
 8 
 9 Fraction::Fraction(const Fraction& f): up{f.up},down{f.down} {}
10 
11 int Fraction::gcd(int a,int b){
12     while(b!=0){
13         int r=a%b;
14         a=b;
15         b=r;
16     }
17     return a;
18 }
19 
20 void Fraction::simplify(){
21     if(down<0)
22     {
23         up=-up;
24         down=-down;
25     }
26     int k=gcd(up,down);
27     up=up/k;
28     down=down/k;
29 }
30 
31 Fraction::Fraction(int up,int down):up{up},down{down}{
32     if (down == 0) {
33         cout<<"分母不能为0"<<endl;
34     }
35     simplify();}
36 
37 int Fraction::get_up()const{
38     return up;
39 }
40 int Fraction::get_down()const{
41     return down;
42 }
43 
44 
45 Fraction Fraction::negative() const{
46     return Fraction(-up,down);
47 }
48 
49 void output(const Fraction &f) {
50     if(f.get_down()==0)
51     return;
52     else if(f.get_up()==0)
53     cout<<"0";
54     else if(f.get_down()==1)
55     cout<<f.get_up();
56     else if(f.get_up()>0&&f.get_down()>0)
57     cout<<f.get_up()<<"/"<<f.get_down();
58     else if(f.get_up()<0&&f.get_down()<0)
59     cout<<-f.get_up()<<"/"<<-f.get_down();
60     else if(f.get_up()>0&&f.get_down()<0)
61     cout<<-f.get_up()<<"/"<<-f.get_down();
62     else
63     cout<<f.get_up()<<"/"<<f.get_down(); 
64 }
65 
66 
67 Fraction add(const Fraction& f1,const Fraction& f2){
68     return Fraction(f1.get_up()*f2.get_down()+f2.get_up()*f1.get_down(),f1.get_down()*f2.get_down());
69 }
70 Fraction sub(const Fraction& f1,const Fraction& f2){
71     return Fraction(f1.get_up()*f2.get_down()-f2.get_up()*f1.get_down(),f1.get_down()*f2.get_down());
72 }
73 Fraction mul(const Fraction& f1,const Fraction& f2){
74     return Fraction(f1.get_up()*f2.get_up(),f1.get_down()*f2.get_down());
75 }
76 Fraction div(const Fraction& f1,const Fraction& f2){
77     return Fraction(f1.get_up()*f2.get_down(),f1.get_down()*f2.get_up());
78 }

 

task4.cpp
#include "Fraction.h"
#include <iostream>

using std::cout;
using std::endl;


void test1() {
    cout << "Fraction类测试: " << endl;
    cout << Fraction::doc << endl << endl;

    Fraction f1(5);
    Fraction f2(3, -4), f3(-18, 12);
    Fraction f4(f3);
    cout << "f1 = "; output(f1); cout << endl;
    cout << "f2 = "; output(f2); cout << endl;
    cout << "f3 = "; output(f3); cout << endl;
    cout << "f4 = "; output(f4); cout << endl;

    Fraction f5(f4.negative());
    cout << "f5 = "; output(f5); cout << endl;
    cout << "f5.get_up() = " << f5.get_up() << ", f5.get_down() = " << f5.get_down() << endl;

    cout << "f1 + f2 = "; output(add(f1, f2)); cout << endl;
    cout << "f1 - f2 = "; output(sub(f1, f2)); cout << endl;
    cout << "f1 * f2 = "; output(mul(f1, f2)); cout << endl;
    cout << "f1 / f2 = "; output(div(f1, f2)); cout << endl;
    cout << "f4 + f5 = "; output(add(f4, f5)); cout << endl;
}

void test2() {
    Fraction f6(42, 55), f7(0, 3);
    cout << "f6 = "; output(f6); cout << endl;
    cout << "f7 = "; output(f7); cout << endl;
    cout << "f6 / f7 = "; output(div(f6, f7)); cout << endl;
}

int main() {
    cout << "测试1: Fraction类基础功能测试\n";
    test1();

    cout << "\n测试2: 分母为0测试: \n";
    test2();
}

 

运行结果截图:

 

任务5: account.h
 1 #pragma once
 2 #include<iostream>
 3 
 4 class SavingAccount {
 5 private:
 6     int id;
 7     double balance;
 8     double rate;
 9     int lastDate;
10     double accumulation;
11     static double total;
12     void record(int date,double amount);
13     double accumulate(int date) const {
14         return accumulation+balance*(date-lastDate);    
15     }    
16 public:
17     SavingAccount(int date,int id,double rate);
18     int getID() const {return id;}
19     double getBalance() const {return balance;}
20     double getRate() const {return rate;}
21     static double getTotal() {return total;}
22     void deposit(int date,double amount);
23     void withdraw(int date,double amount);
24     void settle(int date);
25     void show() const; 
26 };

 

account.cpp
 1 #include"account.h"
 2 #include<iostream>
 3 #include<cmath>
 4 
 5 using namespace std;
 6 
 7 double SavingAccount::total = 0;
 8 SavingAccount::SavingAccount(int date,int id,double rate): id(id),balance(0),rate(rate),lastDate(date),accumulation(0) {
 9     cout<<date<<"\t#"<<id<<"is created"<<endl;
10 }
11 
12 void SavingAccount::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     cout<<date<<"\t#"<<id<<"\t"<<amount<<"\t"<<balance<<endl;
19 }
20 
21 void SavingAccount::deposit(int date,double amount) {
22     record(date,amount); 
23 }
24 
25 void SavingAccount::withdraw(int date,double amount) {
26     if(amount>getBalance())
27         cout<<"Error:not enough money"<<endl;
28     else
29         record(date,-amount);
30 }
31 
32 void SavingAccount::settle(int date) {
33     double interst = accumulate(date)*rate/365;
34     if(interst != 0)
35         record(date,interst);
36     accumulation = 0;
37 }
38 
39 void SavingAccount::show() const {
40     cout<<"#"<<id<<"\tBalance:"<<balance;
41 }

 

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

 

运行截图:

 

思考: SavingAccount 类的接口和内部计算模块基本上是合理的,能够实现储蓄账户的基本功能,如存款、取款、结算和显示账户状态。 在此基础上,对输入参数的有效性检查在存款、取款和结算操作中,应该检查输入参数的有效性。 可以考虑将结算逻辑(利息计算)与账户操作分开,或者将结算逻辑抽象到一个单独的服务类中。这样可以简化 SavingAccount 类的复杂度。   实验总结: 代码组织我们将类的声明与实现分离,使用头文件(.h)和实现文件(.cpp)的形式,增强了代码的可管理性和可读性。这种组织方式使得项目结构更加清晰。 通过封装与接口实现了封装的核心概念,通过将数据成员(如 balance 和 rate)设为 private,并为其提供公有的操作方法(如 depositwithdraw 和 settle)。这种方式使得外部对象无法直接修改内部状态,从而保护了数据的完整性。熟悉了C++的类定义语法,包括构造函数、析构函数的使用。实践了访问权限控制,确保了类的成员在适当的封装级别下进行访问。

标签:std,const,对象,编程,int,Complex,实验,Fraction,include
From: https://www.cnblogs.com/fngwj/p/18511315

相关文章

  • 实验3
    实验一:1#include<stdio.h>23charscore_to_grade(intscore);45intmain(){6intscore;7chargrade;89while(scanf("%d",&score)!=EOF){10grade=score_to_grade(score);11printf("分数:%d,等级:%c\n\n"......
  • 现在职业PHP 程序员通常用什么编程工具
    标题:现代职业PHP程序员通常使用的编程工具开头段落:现代职业PHP程序员通常使用的编程工具主要包括集成开发环境(IDE)、版本控制系统、调试工具、数据库管理工具、以及代码质量工具。这些工具共同构建了PHP开发的基础框架,使开发工作更加高效、组织化。特别地,集成开发环境(IDE)无疑是......
  • 记一个mysql 主从切换的实验记录
    一、前言msyql切换主库一般都是用高可用方案,例如MHA,MGR,高可用方案可以自动切主,但是MHA的failover功能无法把旧主自动挂到新主上作为从库使用,所以发生failover后,还需要手动把旧的主库作为备库挂到新的主库上。此时常规操作就是备份新主库,然后应用到旧主库上,然后再重新搭建主从。......
  • 实验2 类和对象 基础编程1
    实验任务1:源代码t.h:点击查看代码#pragmaonce#include<string>//类T:声明classT{//对象属性、方法public:  T(intx=0,inty=0); //普通构造函数  T(constT&t); //复制构造函数  T(T&&t);   //移动构造函数  ~T();     //析......
  • 实验3
    实验任务1:1#include<stdio.h>2charscore_to_grade(intscore);3intmain(){4intscore;5chargrade;67while(scanf("%d",&score)!=EOF){8grade=score_to_grade(score);9printf("分数:%d,......
  • C++ 网络编程 IO多路复用、select、poll、epoll知识点总结
    1.什么是I/O多路复用?I/O多路复用(I/OMultiplexing)是一种编程技术,允许一个线程或进程同时管理多个I/O通道(如文件描述符、套接字等)。它使得单个进程能够在不使用多个线程或进程的情况下,同时处理多个I/O操作。这在网络编程和高性能服务器中尤为重要,因为它可以有效地利用系......
  • JUC并发编程1
    JUC并发编程1.常见的加锁方式1.1synchronized关键字要求:多个线程并行执行,依次实现对数字的+1、-1操作。即一次+1、一次-1,依次执行。Share类classShare{privateintnumber=0;publicsynchronizedvoidincr()throwsInterruptedException{//......
  • 实验三
    实验一:源代码:1#include<stdio.h>2charscore_to_grade(intscore);3intmain(){4intscore;5chargrade;67while(scanf("%d",&score)!=EOF){8grade=score_to_grade(score);9printf(&quo......
  • 《DNK210使用指南 -CanMV版 V1.0》第三十四章 image图像滤波实验
    第三十四章image图像滤波实验1)实验平台:正点原子DNK210开发板2)章节摘自【正点原子】DNK210使用指南-CanMV版V1.03)购买链接:https://detail.tmall.com/item.htm?&id=7828013987504)全套实验源码+手册+视频下载地址:http://www.openedv.com/docs/boards/k210/ATK-DNK210.html5)......
  • 实验3(2.0)
    任务1#include<stdio.h>charscore_to_grade(intscore);intmain(){intscore;chargrade;while(scanf("%d",&score)!=EOF){grade=score_to_grade(score);printf("分数:%d,等级:%c\n\n",score,g......