在一些语言,例如python
等中都有以下的设计,一个变量可以接受任意类型的值:
x = 3
x = 1.22
x = "hello"
我们在C/C++中是否可以实现类似的功能呢,本文主要来介绍一个简单Any类的实现,这个类可以接收任意的其他类型(动态类型)。
其实在C++17已经给出了一个这样的类std::any,感兴趣可以去看:
https://zh.cppreference.com/w/cpp/utility/any
- 要想实现动态类型,我们其实可以通过以下方法
- C语言的
void*
class A{};
class B {};
int main() {
void* ptr = new A();
ptr = new B();
}
- C++里的继承关系,基类指向派生类
class A{};
class B : public A{};
int main() {
A* ptr = new B();
}
因为我们是要实现C++的,所以我们利用父类指针可以指向子类来实现一个Any类;实现思路如下
- 考虑到要接收任意类型,所以这里是需要用到模版的
- 能让一个类型指向其他的任意类型,采用基类指向派生类
- 话不多说直接给出代码
// 可以接收任意数据的类型
class Any
{
public:
Any() = default;
~Any() = default;
Any(const Any&) = delete;
Any& operator=(const Any&) = delete;
Any(Any&&) = default;
Any& operator=(Any&&) = default;
// 这个构造函数可以让Any类型接收任意其它的数据
template<typename T> // T:int Derive<int>
Any(T data) : base_(std::make_unique<Derive<T>>(data))
{}
// 这个方法能把Any对象里面存储的data数据提取出来
template<typename T>
T get_cast()
{
// 我们怎么从base_找到它所指向的Derive对象,从它里面取出data成员变量
// 基类指针 -> 派生类指针 RTTI
Derive<T>* pd = dynamic_cast<Derive<T>*>(base_.get());
if (pd == nullptr)
{
throw "type is unmatch!";
}
return pd->data_;
}
private:
// 基类类型
class Base
{
public:
virtual ~Base() = default;
};
// 派生类类型
template<typename T>
class Derive : public Base
{
public:
Derive(T data) : data_(data)
{}
T data_; // 保存了任意的其它类型
};
private:
// 定义一个基类的指针,这里直接使用智能指针来管理
std::unique_ptr<Base> base_;
};
int main() {
Any x = 10;
Any str = "hello";
int a = x.get_cast<int>();
std::string s = str.get_cast<std::string>();
return 0;
}