• 1.1.C++项目:仿muduo库实现并发服务器之any类的设计


    一、思想

    每⼀个Connection对连接进行管理,最终都不可避免需要涉及到应用层协议的处理,因此在Connection中需要设置协议处理的上下文来控制处理节奏。但是应用层协议千千万,为了降低耦度,这个协议接收解析上下文就不能有明显的协议倾向,它可以是任意协议的上下文信息,因此就需要⼀个通⽤的类型来保存各种不同的数据结构。
    在C语言中,通用类型可以使用void*来管理,但是在C++中,boost库和C++17给我们提供了一个通用类型any来灵活使用,如果考虑增加代码的移植性,尽量减少第三方库的依赖,则可以使用C++17特性中的any,或者自己来实现。而这个any通用类型类的实现其实并不复杂,以下是简单的部分实现。

    二、框架

    /*Any类主要是实现⼀个通⽤类型出来,在c++17和boost库中都有现成的可以使⽤,但是这⾥实现⼀下
    了解其思想,这样也就避免了第三⽅库的使⽤了*/
    
    /*⾸先Any类肯定不能是⼀个模板类,否则编译的时候 Any a, Anyb,需要传类型作
    为模板参数,也就是说在使⽤的时候就要确定其类型*/
    /*这是⾏不通的,因为保存在Content中的协议上下⽂,我们在定义any对象的时候是不知道他们的协
    议类型的,因此⽆法传递类型作为模板参数*/
    /*因此考虑Any内部设计⼀个模板容器holder类,可以保存各种类型数据*/
    /*⽽因为在Any类中⽆法定义这个holder对象或指针,因为any也不知道这个类要保存什么类型的数
    据,因此⽆法传递类型参数*/
    /*所以,定义⼀个基类placehoder,让holder继承于placeholde,⽽Any类保存⽗类指针即可*/
    /*当需要保存数据时,则new⼀个带有模板参数的⼦类holder对象出来保存数据,然后让Any类中的⽗
    类指针,指向这个⼦类对象就搞定了*/
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    三、代码

    class Any{
        private:
            class holder {
                public:
                    virtual ~holder() {}
                    virtual const std::type_info& type() = 0;
                    virtual holder *clone() = 0;
            };
            template<class T>
            class placeholder: public holder {
                public:
                    placeholder(const T &val): _val(val) {}
                    // 获取子类对象保存的数据类型
                    virtual const std::type_info& type() { return typeid(T); }
                    // 针对当前的对象自身,克隆出一个新的子类对象
                    virtual holder *clone() { return new placeholder(_val); }
                public:
                    T _val;
            };
            holder *_content;
        public:
            Any():_content(NULL) {}
            template<class T>
            Any(const T &val):_content(new placeholder<T>(val)) {}
            Any(const Any &other):_content(other._content ? other._content->clone() : NULL) {}
            ~Any() { delete _content; }
    
            Any &swap(Any &other) {
                std::swap(_content, other._content);
                return *this;
            }
    
            // 返回子类对象保存的数据的指针
            template<class T>
            T *get() {
                //想要获取的数据类型,必须和保存的数据类型一致
                assert(typeid(T) == _content->type());
                return &((placeholder<T>*)_content)->_val;
            }
            //赋值运算符的重载函数
            template<class T>
            Any& operator=(const T &val) {
                //为val构造一个临时的通用容器,然后与当前容器自身进行指针交换,临时对象释放的时候,原先保存的数据也就被释放
                Any(val).swap(*this);
                return *this;
            }
            Any& operator=(const Any &other) {
                Any(other).swap(*this);
                return *this;
            }
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
  • 相关阅读:
    【SpringCloud-学习笔记】Ribbon负载均衡
    linux日志查看技巧
    SQLZOO:SELECT from WORLD
    PTA题目 福到了
    手机异步发送短信验证码解决方案-Celery+redis
    【Java并发编程】——线程池
    IN动态|小达智能科技领导一行莅临英码科技调研,携手打造时代特色的AI教学平台
    Google Earth Engine APP——在线计算23类植被指数app代码
    线程池简单介绍
    02【HTML快速入门】
  • 原文地址:https://blog.csdn.net/weixin_54447296/article/details/133770300