类结构
-
Holder 基类
- 这是一个虚基类,用于存储任何类型的值。
- 定义了虚析构函数、获取类型信息的虚函数
type()
和克隆对象的虚函数clone()
。
-
PlaceHolder 模板类
- 这是Holder的子类,用于实际存储特定类型的值。
- 它有一个模板参数
T
,并包含一个类型为T
的成员变量_val
。 - 重写了
type()
和clone()
方法,分别返回当前存储值的类型信息和创建一个新的PlaceHolder
实例。
成员变量
_content
:一个指向Holder基类的指针,用于存储实际的值。
构造函数和析构函数
-
默认构造函数
- 初始化
_content
为NULL
。
- 初始化
-
模板构造函数
- 接受一个类型为
T
的值,并创建一个PlaceHolder<T>
实例来存储它。 - 将
_content
指向新创建的PlaceHolder<T>
实例。
- 接受一个类型为
-
拷贝构造函数
- 如果
_content
不为空,则调用clone()
方法创建一个新的Holder实例。 - 将
_content
指向新创建的Holder实例。
- 如果
-
析构函数
- 删除
_content
指向的Holder实例。
- 删除
赋值运算符
-
模板赋值运算符
- 接受一个类型为
T
的值,并创建一个临时的Any
对象来存储它。 - 使用
swap
方法交换当前对象和临时对象的内容。 - 返回当前对象的引用。
- 接受一个类型为
-
拷贝赋值运算符
- 类似于模板赋值运算符,但用于拷贝另一个
Any
对象。
- 类似于模板赋值运算符,但用于拷贝另一个
辅助函数
- swap:一个私有成员函数,用于交换两个
Any
对象的_content
指针。
get 方法
-
模板 get 方法
- 接受一个类型参数
T
,并断言当前存储的类型与T
一致。 - 将
_content
强制转换为PlaceHolder<T>*
类型,并返回其_val
成员变量的地址。
- 接受一个类型参数
注意事项
- 类型安全:通过虚函数和模板确保了类型安全。在调用
get<T>()
时,如果存储的类型与T
不匹配,assert
会触发。 - 资源管理:正确地管理了内存,确保了
_content
指向的Holder实例在不再需要时被删除。 - 异常安全:我没有显式处理异常,但所有操作都是基于指针和内存分配,因此可能会抛出异常(如
std::bad_alloc
)。在实际使用中,调用者可能需要考虑异常处理。 - 性能:由于使用了虚函数和动态内存分配,这个实现可能比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; }
};