首页 > 编程语言 >C++ Practical-2 day2 运算符重载之时钟类++运算符

C++ Practical-2 day2 运算符重载之时钟类++运算符

时间:2024-09-28 15:47:56浏览次数:3  
标签:currentTime ++ Clock day2 运算符 时间 重载

系列文章目录

点击直达——文章总目录


文章目录


C++ Practical-2 day2 运算符重载之时钟类++运算符

Overview

  • C++不练习coding,就相当于空中楼阁,基础不扎实
  • 光吃不干,等于没吃
  • clock_overloading

1.时间类 重载后缀++运算符来递增时间

在C++中创建一个时钟类并重载函数调用运算符(),可以使得该类的实例可以像函数一样被调用,以执行特定的操作,比如获取当前时间、设置时间等。

下面是一个简单的示例,展示如何定义一个时钟类,该类重载了函数调用运算符来获取当前时间:

为了实现通过重载后缀++运算符来递增时间,我们需要在Clock类中添加一个特殊的成员函数。这个成员函数将实现后缀递增操作。

#include <iostream>
#include <ctime>

class Clock {
private:
    time_t currentTime;

public:
    // 构造函数
    Clock() {
        currentTime = time(0); // 初始化为当前时间
    }

    // 重载()运算符,返回当前时间的字符串表示
    std::string operator()() const { // 保持const
        tm *ltm = localtime(&currentTime); // 转换为本地时间
        char buffer[80];
        strftime(buffer, 80, "%Y-%m-%d %H:%M:%S", ltm); // 格式化时间
        return std::string(buffer);
    }

    // 设置时间
    void setTime(time_t newTime) {
        currentTime = newTime;
    }

    // 获取时间
    time_t getTime() const {
        return currentTime;
    }

    // 计算两个时间点之间的差异(秒)
    double timeDifference(const Clock &other) const {
        return difftime(other.currentTime, currentTime);
    }

    // 时间递增
    void incrementTime(int seconds) {
        currentTime += seconds;
    }

    // 重载前置++运算符
    Clock& operator++() {
        incrementTime(1); // 递增1秒
        return *this;
    }

    // 重载后置++运算符
    Clock operator++(int) {
        Clock temp = *this; // 保存当前状态
        incrementTime(1);   // 递增1秒
        return temp;       // 返回递增前的状态
    }
};

int main() {
    Clock myClock;
    std::cout << "Current time: " << myClock() << std::endl;

    // 手动设置时间
    myClock.setTime(time(0)); // 重新设置为当前时间
    std::cout << "Current time after setting: " << myClock() << std::endl;

    // 创建另一个时钟实例
    Clock anotherClock;
    anotherClock.setTime(time(0) + 3600); // 设置为当前时间1小时后

    // 计算两个时间点之间的差异
    double diff = myClock.timeDifference(anotherClock);
    std::cout << "Time difference: " << diff << " seconds" << std::endl;

    // 使用后置++运算符递增时间
    myClock++;
    std::cout << "Current time after incrementing: " << myClock() << std::endl;

    return 0;
}

1.1.解释

  1. 重载后缀++运算符

    • 功能:实现后缀递增操作,即每次调用myClock++时,currentTime递增1秒。
    • 返回值:返回Clock对象的引用,允许链式调用。
  2. main函数

    • 创建Clock类的实例myClock
    • 使用重载的()运算符获取并打印当前时间。
    • 手动设置时间,并再次打印当前时间。
    • 计算两个时间点之间的差异,并打印结果。
    • 使用后缀++运算符递增时间,并打印递增后的时间。
  3. Clock类

    • 私有成员变量currentTime,用于存储时间。
    • 构造函数:初始化currentTime为当前时间。
    • 重载的()运算符:返回当前时间的字符串表示。它使用time()函数获取当前时间,然后使用localtime()将其转换为本地时间,最后使用strftime()格式化时间字符串。
    • setTime成员函数:允许设置时间。
    • getTime成员函数:返回当前时间。

通过这种方式,Clock类现在可以通过重载后缀++运算符来递增时间,使得代码更加简洁和直观。

1.2.注意事项

  1. const修饰符:如果你的重载的()运算符不会修改对象的状态,你应该在函数声明的末尾添加const关键字,以表明这个成员函数不会修改对象的任何成员变量。

  2. 参数:你可以为()运算符提供参数,比如设置时间。

  3. 返回类型:你需要指定函数调用的返回类型。

通过这种方式,你可以创建一个非常灵活的时钟类,该类的对象可以像函数一样被调用,以执行特定的操作。

2.如何确保时间递增操作在多线程环境中是线程安全的?

为了确保时间递增操作在多线程环境中是线程安全的,我们需要确保当多个线程尝试同时修改时间时,这些修改不会相互干扰,导致数据不一致。这通常涉及到使用同步机制,如互斥锁(mutexes),来保护对共享资源的访问。

以下是一些确保线程安全的方法:

  1. 使用互斥锁(Mutex)
    在C++中,可以使用std::mutex来确保只有一个线程可以同时修改时间。在递增时间的函数中,我们需要在修改时间之前获取锁,并在修改后释放锁。

     #include <string>
     #include <mutex>
     #include <ctime>
    
     class Clock {
     private:
         time_t currentTime;
         mutable std::mutex mtx; // 使用mutable因为mtx在const成员函数中使用
    
     public:
         Clock() {
             currentTime = time(0);
         }
    
         // 重载()运算符
         std::string operator()() const {
             std::lock_guard<std::mutex> lock(mtx); // 使用lock_guard自动加锁和解锁
             tm  *ltm = localtime(&currentTime);
             char buffer[80];
             strftime(buffer, 80, "%Y-%m-%d %H:%M:%S", ltm);
             return std::string(buffer);
         }
    
         // 线程安全的时间递增
         void incrementTime(int seconds) {
             std::lock_guard<std::mutex> lock(mtx);
             currentTime += seconds;
         }
    
         // 重载后缀++运算符
         Clock &operator++() {
             incrementTime(1);
             return *this;
         }
     };
    
  2. 使用原子操作
    如果时间递增操作可以被设计为原子操作,那么可以使用std::atomic来确保操作的原子性。

    #include <atomic>
    #include <ctime>
    
    class Clock {
    private:
        std::atomic<time_t> currentTime;
    
    public:
        Clock() {
            currentTime.store(time(0));
        }
    
        void incrementTime(int seconds) {
            currentTime.fetch_add(seconds, std::memory_order_relaxed);
        }
    
        Clock& operator++() {
            incrementTime(1);
            return *this;
        }
    };
    
  3. 使用条件变量
    如果需要更复杂的线程间协调,可以使用std::condition_variable来等待和通知时间变化。

  4. 避免共享
    如果可能,避免共享时间对象,每个线程可以使用本地时间副本,然后定期同步。

  5. 使用线程安全的类
    使用标准库中已经保证线程安全的类,如std::chrono中的一些类。

确保线程安全通常需要仔细设计,并且在多线程程序中进行充分的测试,以确保没有死锁或竞态条件。


关于作者

标签:currentTime,++,Clock,day2,运算符,时间,重载
From: https://blog.csdn.net/wesigj/article/details/142603004

相关文章

  • 10.C++程序中的循环语句
    C++中提供了三种循环语句(for循环,while循环以及do-while循环)来使程序员可以更方便地对数据进行迭代操作。if语句for语句的格式为:for(初始化语句;循环条件;迭代语句){代码块}for循环首先会执行初始化语句,主要是用于初始化循环变量和其它变量,然后判断条件是否为真,如果为真,则执......
  • 【C++】set与map
    一、什么是set、mapset和map是专门用来搜索的数据结构,是一种适合查找的容器,set和map的底层是二叉搜索树。*setset的声明:set<T>set中的相同元素只能存在一个。multiset(与set用法相同)可以存放多个相同元素。*mapmap的声明:map<T1,T2>map存储的匀速是pairmap中的与T1......
  • 【C++篇】迈入新世界的大门——初识C++(下篇)
    文章目录   前言   引用        引用的概念和定义        引用的特性        引用的使用        const引用        指针和引用的关系  inline         ......
  • 运算符
    短路运算publicclassOperator02{publicstaticvoidmain(String[]args){//短路运算//c<4false,不执行后面半句(c++<4),c还是5没有自增intc=5;booleand=(c<4)&&(c++<4);System.out.println(d);Syst......
  • 《 C++ 修炼全景指南:十三 》为什么你的代码不够快?全面掌控 unordered_set 和 unordere
    摘要本文深入探讨了C++标准库中的两大无序容器——unordered_set和unordered_map,从底层实现、核心操作、性能优化、实际应用等多个方面进行了全面分析。首先,文章介绍了这两种容器的基本概念,说明了它们基于哈希表实现的特点,尤其是在查找、插入和删除操作上具备常数时间......
  • PointNet++论文介绍和代码实现
    一、PointNet++论文详细介绍1.背景与动机点云数据的重要性:在3D计算机视觉和图形学中,点云是一种常见的数据表示方式,广泛应用于3D扫描、自动驾驶、机器人导航等领域。PointNet的局限性:PointNet是处理点云的开创性工作,但由于其直接对全局点集进行特征学习,无法有效捕捉局部特征,......
  • C++设计模式
    C++设计模式提供了一些常见的问题和解决方案,帮助我们写出更清晰、更高效、更容易维护的代码。1.单例模式:就像整形诊所里有一个特别的规定,全世界只能有一个人拥有某款独一无二的鼻子,其他人都不能复制。(确保一个类只有一个实例,并提供一个全局访问点。)classSingleton{priva......
  • C C++ 强制类型转换
    强制类型转换概念在C语言中,强制类型转换(强转)是一种将一个数据类型的值转换为另一个数据类型的操作。它允许程序员显式地改变表达式的数据类型。语法强转的语法形式为:(目标类型)表达式。例如,(int)3.14会将浮点数3.14强制转换为整数类型,结果为3。作用不同类型数据运算时......
  • 【C++】string中常用的接口
    目录前言常用接口1.有/无参string2.字符串相加3.string类对象的访问及遍历操作3.1普通遍历3.2迭代器遍历3.3范围for4.string类对象的修改操作前言今天分享一些个人认为string常用的接口,大多数资料来自于cplusplus,其他不常用的平常查阅资料使用即可。需要测试代......
  • 运算符、分支语句
    位操作符:可以直接操作二进制数位的内容;~是一个单目位操作符,它可以根据一个数字计算另外一个数字,这两个数字所有二进制数位的内容都不同(按位取反),使用的时候这个符号应该写在数字前面双目位操作符:包括按位与(&),按位或(|)以及按位异或(^),他们都可以把两个数字对应二进制数位的内容做计算......