C++ 17 any 类的简单模拟实现

admin2024-04-03  0

类结构

  1. Holder 基类

    • 这是一个虚基类,用于存储任何类型的值。
    • 定义了虚析构函数、获取类型信息的虚函数type()和克隆对象的虚函数clone()
  2. PlaceHolder 模板类

    • 这是Holder的子类,用于实际存储特定类型的值。
    • 它有一个模板参数T,并包含一个类型为T的成员变量_val
    • 重写了type()clone()方法,分别返回当前存储值的类型信息和创建一个新的PlaceHolder实例。

成员变量

  • _content:一个指向Holder基类的指针,用于存储实际的值。

构造函数和析构函数

  1. 默认构造函数

    • 初始化_contentNULL
  2. 模板构造函数

    • 接受一个类型为T的值,并创建一个PlaceHolder<T>实例来存储它。
    • _content指向新创建的PlaceHolder<T>实例。
  3. 拷贝构造函数

    • 如果_content不为空,则调用clone()方法创建一个新的Holder实例。
    • _content指向新创建的Holder实例。
  4. 析构函数

    • 删除_content指向的Holder实例。

赋值运算符

  1. 模板赋值运算符

    • 接受一个类型为T的值,并创建一个临时的Any对象来存储它。
    • 使用swap方法交换当前对象和临时对象的内容。
    • 返回当前对象的引用。
  2. 拷贝赋值运算符

    • 类似于模板赋值运算符,但用于拷贝另一个Any对象。

辅助函数

  • swap:一个私有成员函数,用于交换两个Any对象的_content指针。

get 方法

  • 模板 get 方法

    • 接受一个类型参数T,并断言当前存储的类型与T一致。
    • _content强制转换为PlaceHolder<T>*类型,并返回其_val成员变量的地址。

注意事项

  1. 类型安全:通过虚函数和模板确保了类型安全。在调用get<T>()时,如果存储的类型与T不匹配,assert会触发。
  2. 资源管理:正确地管理了内存,确保了_content指向的Holder实例在不再需要时被删除。
  3. 异常安全:我没有显式处理异常,但所有操作都是基于指针和内存分配,因此可能会抛出异常(如std::bad_alloc)。在实际使用中,调用者可能需要考虑异常处理。
  4. 性能:由于使用了虚函数和动态内存分配,这个实现可能比C++17标准库中的std::any稍微慢一些。
class Any
{
    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) {}
        ~PlaceHolder() {}
        virtual const std::type_info &type() { return typeid(T); }
        virtual Holder *clone() { return new PlaceHolder(_val); }

    public:
        T _val;
    };

private:
    Holder *_content;

private:
    void swap(Any &a)
    {
        std::swap(_content, a._content);
    }

public:
    Any() : _content(NULL) {}
    template <class T>
    Any(const T &val) : _content(new PlaceHolder<T>(val)) {}
    Any(const Any &a) : _content(a._content ? a._content->clone() : NULL) {}

    template <class T>
    Any &operator=(const T &val)
    {
        Any(val).swap(*this);
        return *this;
    }

    Any &operator=(const Any &a)
    {
        Any(a).swap(*this);

        return *this;
    }

    template <class T>
    T *get()
    {
        assert(typeid(T) == _content->type()); // 类型必须一致
        return &(((PlaceHolder<T> *)_content)->_val);
    }

    ~Any() { delete _content; }
};
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明原文出处。如若内容造成侵权/违法违规/事实不符,请联系SD编程学习网:675289112@qq.com进行投诉反馈,一经查实,立即删除!