当前位置: 首页 > article >正文

类的动态演绎:程序运行中的生命绽放

任务1.按照要求设计类(根据输出设计类)

设计类就是根据数据封装的要求,抽象出适合的类。

有如下情况的测试程序和测试程序的输出结果,要求设计类Smile。

(一)第1种情况:

(1)测试程序如下:

int main()

{

    cout<<"科艺欢迎你!"<<endl;

    return 0;

}

(2)测试程序的输出结果如右图:

(3)此题要求定义两个对象变量

(二)第二种情况:

(1)测试程序如下:

int main()

{

    Smile we;

    Smile you(we);

    you.Display();

    you.Set(“Thank you.”);

    cout<<you.Get()<<endl;

    you.talk();

you.Display();

return 0;

}

(2)测试程序的输出结果如右图:

注:

  • 后面5行为倒数第6行输出后接下去的输出内容。
  • 倒数第1和2行调用析构函数
  • 倒数第3行调用Display函数

(3)设计类Smile 的原则:

1)在头文件Smile.h 中声明类

2)在Smile.cpp中实现类

3)使用内联函数定义Display()函数

4)演示文件名用学号作主名。

任务一

主要思路

一、关于 Hello.h 文件

  1. 头文件保护机制
    • 使用 #pragma once 和 #ifndef HELLO_H#define HELLO_H#endif // HELLO_H 结构来防止头文件被重复包含。这确保在编译过程中,无论该头文件在多个源文件中被引用多少次,其内容都只会被编译一次,避免了因重复定义等问题导致的编译错误。
  2. 类的声明
    • 声明了一个名为 Hello 的类,将其访问控制修饰符设置为 publicprotected 和 private 来划分不同成员的访问权限范围。
    • 在 public 部分声明了构造函数 Hello(string),用于初始化类对象时传入特定的字符串参数,还声明了虚析构函数 virtual ~Hello(),虚析构函数的存在使得在通过基类指针释放派生类对象内存时能够正确调用派生类的析构函数,保证资源的正确释放和避免内存泄漏等问题(虽然当前代码中没有体现派生类相关情况,但这种良好的设计习惯便于后续扩展)。
    •  private 部分定义了一个字符串类型的成员变量 name,用于存储与类相关的特定名称信息,外部不能直接访问该变量,只能通过类提供的公有接口来操作它。

二、关于 Hello.cpp 文件

  1. 构造函数的实现
    • 实现了 Hello 类的构造函数 Hello::Hello(string x),通过成员初始化列表的方式用传入的参数 x 初始化了私有成员变量 name,并且在构造函数体中输出了一句问候语 "Hi " << name << "!" << endl,意味着每当创建一个 Hello 类的对象时,都会向控制台打印出对应的问候信息,告知使用者对象的创建以及对应的名称。
  2. 析构函数的实现
    • 实现了 Hello 类的析构函数 Hello::~Hello(),在析构函数体中输出了告别语 "GoodBye " << name << "!" << endl,表明当对象生命周期结束被销毁时,会向控制台打印相应的告别信息,有助于追踪对象的销毁情况以及进行一些资源清理等相关的提示操作(虽然当前简单示例中没有复杂的资源管理,但遵循了合理的编程规范)。
  3. 全局对象定义
    • 在该文件中定义了两个 Hello 类的全局对象 a("Rose") 和 b("Jose"),这意味着在程序启动时,这两个对象就会被创建,进而会自动调用 Hello 类的构造函数,向控制台分别输出对应的问候语。在程序结束时,它们的析构函数也会被自动调用,输出相应的告别语,展示了对象从创建到销毁的完整生命周期过程。

三、关于 main.cpp 文件

  1. 主函数功能
    • 主函数 main 是整个程序的入口点,在当前代码中,它仅仅向控制台输出了一句 "科艺欢迎你!" 的欢迎信息,并没有直接和 Hello 类进行交互,其功能相对比较独立简单,只是起到一个简单的程序启动提示作用。

Hello.h

#pragma once
#ifndef HELLO_H
#define HELLO_H
#include <iostream>
#include <string>

using namespace std;

class Hello
{
public:
    Hello(string);
    virtual ~Hello();

protected:

private:
    string name;
};

#endif // HELLO_H


Hello.cpp

#include "Hello.h"

Hello::Hello(string x) :name(x)
{
    cout << "Hi " << name << "!" << endl;
}

Hello::~Hello()
{
    cout << "GoodBye " << name << "!" << endl;
}

Hello a("Rose");
Hello b("Jose");

 

main.cpp

#include <iostream>
using namespace std;

int main()
{
	cout << "科艺欢迎你!" << endl;
	return 0;
}

 

任务二

主要思路

一、关于 Smile.h 文件

  1. 头文件保护机制与包含必要头文件
    • 使用 #pragma once 和 #ifndef SMILE_H#define SMILE_H#endif //SMILE_H 的组合,防止头文件被重复包含,确保代码在编译时的正确性。同时引入 <iostream> 和 <string> 头文件,为后续使用输入输出流以及操作字符串类型做准备。
  2. 类的声明与接口定义
    • 声明了一个名为 Smile 的类,其中在 public 部分定义了多个公有成员函数,构成了类对外提供的接口。
    • 构造函数 Smile(string = "") 采用了默认参数的形式,允许在创建对象时可选择传入一个字符串参数来初始化对象,若不传参则使用默认值。
    • 虚析构函数 virtual ~Smile() 的声明,是为了在存在继承关系时能正确地释放派生类对象的资源,确保内存管理的合理性(虽然当前代码中暂未体现继承相关情况,但这是一种良好的编程习惯)。
    • 拷贝构造函数 Smile(const Smile&) 的声明,用于通过已有对象来初始化新创建的对象,实现对象间的复制操作。
    • 还有 Display()Set(string)Get() 和 talk() 这些成员函数,分别用于展示类的相关信息、设置类内的数据、获取类内的数据以及执行特定的输出操作,这些函数共同定义了类对外的行为和交互方式。
    • 在 private 部分定义了一个字符串类型的成员变量 a,用于存储类内部的数据,外部无法直接访问该变量,只能通过类提供的公有接口来间接操作它。

二、关于 Smile.cpp 文件

  1. 构造函数的实现逻辑
    • 实现了 Smile 类的构造函数 Smile::Smile(string a),通过成员初始化列表用传入的参数初始化成员变量 a,不过在函数体中又将 a 重新赋值为 "Welcome!",并输出该字符串,这意味着每次创建 Smile 类对象时,都会输出 "Welcome!" 作为一种初始的欢迎提示信息。
  2. 析构函数的实现逻辑
    • 实现的析构函数 Smile::~Smile() 会在对象生命周期结束被销毁时输出 "Goobye!",起到提示对象被销毁的作用,便于跟踪对象的生命周期以及进行一些资源释放相关的示意(即便当前简单示例中可能没有复杂资源管理情况)。
  3. 拷贝构造函数的实现逻辑
    • 在拷贝构造函数 Smile::Smile(const Smile& b) 中,先是将传入对象 b 的成员变量 a 的值赋给当前正在创建对象的成员变量 a,然后又将 a 重新赋值为 "Thank you",并且输出该字符串,说明在通过拷贝构造函数创建对象时,会进行这样特定的数据赋值与提示输出操作,体现了拷贝构造的具体行为特点。
  4. Display 函数的实现逻辑
    • Display 函数内部定义了一个静态局部变量 x,每次调用该函数时,会先判断 x 的值,如果 x 不为 0 则输出 "OK",然后 x 的值自增 1。这样的设计使得该函数首次调用和后续调用会有不同的输出表现,可用于在多次调用该函数时进行一些状态的区分或者提示信息的阶段性展示。
  5. Set 函数的实现逻辑
    • Set 函数通过一个循环不断提示用户输入内容,使用 getline(cin, a) 按行读取用户输入的字符串,当输入为 "OK" 时才跳出循环,并且在每次读取非 "OK" 的输入后会输出刚读取的字符串内容,实现了一种从用户输入获取并处理数据的交互逻辑,用于设置类内部的成员变量 a 的值。
      a` 的值。
  6. Get 函数的实现逻辑
    • Get 函数简单地返回固定字符串 "All right",可看作是对外提供一种获取类内固定格式数据或者状态信息的方式,外部通过调用该函数能得到这个特定的返回值。
  7. talk 函数的实现逻辑
    • talk 函数只是简单地输出 "Goobye!",可以理解为执行了类所定义的一种特定的行为或者话语输出,对外展示了类的某一种交互动作。

三、关于 main.cpp 文件

  1. 主函数中的对象操作与函数调用逻辑
    • 在主函数中,首先创建了两个 Smile 类的对象 we 和 you,创建 you 对象时使用了拷贝构造函数,以 we 为蓝本进行初始化,这个过程会触发相应构造函数和拷贝构造函数的执行,输出对应的提示信息。
    • 接着依次调用 you.Display()you.Set("Thankyou.")cout << you.Get() << endlyou.talk() 和再次调用 you.Display(),通过这些函数调用,按照 Smile 类定义的接口逻辑,实现了展示对象状态、设置对象数据、获取对象信息、执行对象特定行为以及再次展示对象状态等一系列操作,展示了类对象在程序运行过程中的完整交互流程与行为表现。

Smile.h

#pragma once
#ifndef SMILE_H
#define SMILE_H
#include <iostream>
#include<string>
using namespace std;

class Smile
{
public:
    Smile(string = "");
    virtual ~Smile();
    Smile(const Smile&);
    void Display();
    void Set(string);
    string Get();
    void talk();
protected:

private:
    string a;
};
#endif //SMILE_H

 

Smile.cpp

#include "Smile.h"
using namespace std;

Smile::Smile(string a) :a(a)
{
    a = "Welcome!";
    cout << a << endl;
}

Smile::~Smile()
{
    cout << "Goobye!" << endl;
}

Smile::Smile(const Smile& b) {
    a = b.a;// // 将传入对象b的成员变量a的值赋给当前正在创建的对象的成员变量a
    a = "Thank you";
    cout << a << endl;
}

void Smile::Display(void)
{
    static int x = 0;
    if (x != 0) cout << "OK" << endl;
    x++;//每次调用函数后,x的值自增1,用于下次判断是否输出"OK"
    return;
}

void Smile::Set(string b)
{
    while (1)
    {
        cout << "输入:";
        getline(cin, a);//将以空格分开的字符串依次读入
        if (a == "OK")
        {
            break;
        }
        cout << "输出:" << a << endl;
    }
    return;
}

string Smile::Get(void)
{
    return "All right";
}

void Smile::talk()
{
    cout << "Goobye!" << endl;
    return;
}

 

main.cpp

#include <iostream>
#include "Smile.h"
using namespace std;
int main()
{
	Smile we;
	Smile you(we);
	you.Display();
	you.Set("Thankyou.");
	cout << you.Get() << endl;
	you.talk();
	you.Display();
	return 0;
}


http://www.kler.cn/a/447529.html

相关文章:

  • 学生管理系统,增加教师管理,班级管理,角色功能权限管理
  • 常用Python自动化测试框架有哪些?
  • JNDI基础
  • asp.net core发布配置端口号,支持linux
  • 【Vulkan入门】16-IndexBuffer
  • Unity 圆形循环复用滚动列表
  • 多模态医学图像融合概述
  • windows C#-静态构造函数
  • 计算机网络之多路转接epoll
  • bestphp‘s revenge
  • linux内核网络分层概述
  • Vue中<script setup></script>的主要语法元素和特性
  • redis开发与运维-redis02-redis数据类型与命令总结
  • 使用C++调用YOLOv8模型的一般步骤
  • 首次成功尝试!使用多模态无监督聚类的语义发现
  • MySQL -- 库的相关操作
  • 性能】JDK和Jmeter的安装与配置
  • 12爬虫:scrapy爬虫框架
  • Day13 苍穹外卖项目 工作台功能实现、Apache POI、导出数据到Excel表格
  • 本地部署 MLflow 服务
  • 中宇联与亚马逊云科技共同推出Well-Architected联合解决方案
  • redis开发与运维-redis03-redis其他数据类型与命令(Bitmaps++HyperLogLog+GEO)
  • 基于pytorch的深度学习基础3——模型创建与nn.Module
  • 设计模式中单例模式中懒汉模式的问题
  • APM32F411使用IIS外设驱动es8388实现自录自播
  • Mono里运行C#脚本2—参数配置