C++ 类 any:使用类型擦除存储任意类型的值
下面是一个简单的实现类'any'的示例代码:
#include <iostream>
#include <typeinfo>
class any {
public:
any() : data(nullptr) {}
template<typename T>
any(const T& value) : data(new holder<T>(value)) {}
any(const any& other) : data(other.data ? other.data->clone() : nullptr) {}
~any() {
delete data;
}
any& operator=(const any& other) {
if (this != &other) {
delete data;
data = (other.data ? other.data->clone() : nullptr);
}
return *this;
}
template<typename T>
any& operator=(const T& value) {
delete data;
data = new holder<T>(value);
return *this;
}
template<typename T>
T cast() const {
if (typeid(T) != data->type()) {
throw std::bad_cast();
}
return static_cast<holder<T>*>(data)->value;
}
private:
struct base_holder {
virtual ~base_holder() {}
virtual base_holder* clone() const = 0;
virtual const std::type_info& type() const = 0;
};
template<typename T>
struct holder : base_holder {
holder(const T& value) : value(value) {}
base_holder* clone() const override {
return new holder(value);
}
const std::type_info& type() const override {
return typeid(T);
}
T value;
};
base_holder* data;
};
int main() {
any a = 5;
std::cout << a.cast<int>() << std::endl;
a = 3.14;
std::cout << a.cast<double>() << std::endl;
try {
std::cout << a.cast<int>() << std::endl;
} catch (const std::bad_cast& e) {
std::cout << 'Failed to cast to int' << std::endl;
}
return 0;
}
在上述代码中,'any'类使用了类型擦除技术,通过'base_holder'作为基类和模板类'holder'作为派生类,来存储不同类型的值。'any'类有一个指向'base_holder'对象的指针'data',通过'data'来访问具体的值。
'any'类的构造函数接受任意类型的值,并根据值的类型创建相应的'holder'对象。拷贝构造函数和赋值运算符重载函数会复制'data'指针指向的'holder'对象。
'cast'函数用于将'any'对象转换为指定类型的值。它首先检查'data'指针指向的对象的类型是否与目标类型一致,如果不一致则抛出'std::bad_cast'异常,否则将'data'转换为'holder'类型并返回具体的值。
在'main'函数中,我们首先将'any'对象'a'赋值为整数5,然后使用'cast'函数将其转换为int类型并输出。然后将'a'赋值为浮点数3.14,再次使用'cast'函数将其转换为double类型并输出。最后,我们尝试将'a'转换为int类型,由于实际存储的是double类型的值,所以会抛出'std::bad_cast'异常。
原文地址: https://www.cveoy.top/t/topic/pYtA 著作权归作者所有。请勿转载和采集!