Lab7: 面向对象程序构造方法及创新应用 (基础)

1、实现一个自定义字符串类型 String,使之具有与 int 等基本类型相同的使用方式。(注:含类、构造、析构、重载等机制运用)

需要分清默认构造函数、拷贝构造函数、带参数构造函数和重载的赋值运算符。

其中加法重载稍微复杂一点。

代码

#include <iostream>
#include <cstring>

class String {
private:
    char* data; // 字符串数据
    size_t length; // 字符串长度

public:
    // 默认构造函数
    String() : data(NULL), length(0) {puts("默认构造");}

    // 构造函数
    String(const char* str) {
    	puts("带参数构造");
        length = strlen(str); // 获取字符串长度
        data = new char[length + 1]; // 分配内存
        strcpy(data, str); // 复制字符串
    }

    // 拷贝构造函数
    String(const String& other) {
        length = other.length; // 获取字符串长度
        data = new char[length + 1]; // 分配内存
        strcpy(data, other.data); // 复制字符串
    }

    // 析构函数
    ~String() {
    	puts("析构"); 
        delete[] data; // 释放内存
    }

    // 重载相加运算符
    String operator+(const String& other) const {
        String result;
        result.length = length + other.length; // 计算结果长度
        result.data = new char[result.length + 1]; // 分配内存
        strcpy(result.data, data); // 复制当前字符串
        strcat(result.data, other.data); // 连接另一个字符串
        return result;
    }

    // 重载相等运算符
    bool operator==(const String& other) const {
        return strcmp(data, other.data) == 0;
    }

    // 重载输出运算符
    friend std::ostream& operator<<(std::ostream& os, const String& str) {
        os << str.data;
        return os;
    }
};

int main() {
    String str1 = "Hello";
    String str2 = "World";
    String str3 = str1 + str2;
	String str4;
	//str4 = str1 + str2; 这一行要用到重载赋值运算符 
    std::cout << str1 << std::endl;
    std::cout << str2 << std::endl;
    std::cout << str3 << std::endl;

    if (str1 == str2) {
        std::cout << "str1 and str2 are equal" << std::endl;
    } else {
        std::cout << "str1 and str2 are not equal" << std::endl;
    }

    return 0;
}
	/*
    // 重载赋值运算符
    String& operator=(const String& other) {
        if (this != &other) {
            delete[] data; // 释放原有内存
            length = other.length; // 获取字符串长度
            data = new char[length + 1]; // 分配新内存
            strcpy(data, other.data); // 复制字符串
        }
        return *this;
    }
    */

输出

image

2、实现一个“字”类型,并通过继承和多态机制分别实现“字”的不同显示、不同字体、不同大小等等。

在上述代码中,我们定义了一个基类 Character,它表示一个字,并具有纯虚函数 display() 用于显示字的内容。然后,我们派生出了三个子类:SongTiCharacter(宋体字)、HeiTiCharacter(黑体字)和 BoldCharacter(加粗字)。每个子类都重写了基类的 display() 函数,以实现不同的显示方式。

在 main() 函数中,我们创建了一个指向基类的指针数组 characters,并分别使用派生类的构造函数创建了三个不同的字对象。通过循环遍历数组,并调用 display() 函数,实现了多态的效果。最后,记得释放动态分配的内存。

代码

#include <iostream>
#include <string>

// 基类:字
class Character {
protected:
    std::string content;

public:
    Character(const std::string& content) : content(content) {}
    virtual ~Character() {}
    virtual void display() const = 0;
};

// 派生类:宋体字
class SongTiCharacter : public Character {
public:
    SongTiCharacter(const std::string& content) : Character(content) {}
    void display() const {
        std::cout << "宋体字:" << content << std::endl;
    }
};

// 派生类:黑体字
class HeiTiCharacter : public Character {
public:
    HeiTiCharacter(const std::string& content) : Character(content) {}
    void display() const {
        std::cout << "黑体字:" << content << std::endl;
    }
};

// 派生类:加粗字
class BoldCharacter : public Character {
public:
    BoldCharacter(const std::string& content) : Character(content) {}
    void display() const {
        std::cout << "加粗字:" << content << std::endl;
    }
};

int main() {
    Character* characters[3];

    characters[0] = new SongTiCharacter("你好");
    characters[1] = new HeiTiCharacter("Hello");
    characters[2] = new BoldCharacter("Bonjour");

    for (int i = 0; i < 3; i++) {
        characters[i]->display();
        delete characters[i];
    }

    return 0;
}

输出

image

3、I/O 流基本应用

通过文件流读取两个含有若干整数的文本文件,将这些整数排序后写入另一个文本文件中。

代码

#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>

int main() {
    // 读取第一个文件的整数
    std::ifstream file1("file1.txt");
    if (!file1) {
        std::cerr << "无法打开文件1" << std::endl;
        return 1;
    }

    std::vector<int> numbers;
    int num;
    while (file1 >> num) {
        numbers.push_back(num);
    }
    file1.close();

    // 读取第二个文件的整数
    std::ifstream file2("file2.txt");
    if (!file2) {
        std::cerr << "无法打开文件2" << std::endl;
        return 1;
    }

    while (file2 >> num) {
        numbers.push_back(num);
    }
    file2.close();

    // 对整数进行排序
    std::sort(numbers.begin(), numbers.end());

    // 写入结果到第三个文件
    std::ofstream outputFile("output.txt");
    if (!outputFile) {
        std::cerr << "无法打开输出文件" << std::endl;
        return 1;
    }

    for (size_t i = 0; i < numbers.size(); i++) {
        outputFile << numbers[i] << " ";
    }
    outputFile.close();

    std::cout << "排序完成,结果已写入output.txt文件" << std::endl;

    return 0;
}

输出(输入输出均在文件内)

排序完成,结果已写入output.txt文件
1 2 3 4 5 6 7 8

4、通过扩展方式定义一个自己的异常类并进行验证。

在这个示例中,我们定义了一个自定义的异常类 MyException,它继承自 std::exception。 what() 函数返回异常消息的字符串表示。

在 divide() 函数中,如果除数为零,我们抛出一个 MyException 异常,并将异常消息作为参数传递给异常的构造函数。

代码

#include <iostream>
#include <stdexcept>

// 自定义异常类
class MyException : public std::exception {
private:
    std::string message;

public:
    MyException(const std::string& msg) : message(msg) {}

    ~MyException() throw() {}

    const char* what() const throw() {
        return message.c_str();
    }
};

// 函数:除法运算
double divide(double dividend, double divisor) {
    if (divisor == 0.0) {
        throw MyException("除数不能为零");
    }
    return dividend / divisor;
}

int main() {
    try {
        double result = divide(10.0, 0.0);
        std::cout << "结果:" << result << std::endl;
    } catch (const MyException& ex) {
        std::cerr << "捕获到自定义异常:" << ex.what() << std::endl;
    }

    return 0;
}

输出

image

posted @ 2023-12-12 16:55  conprour  阅读(20)  评论(0编辑  收藏  举报