C++定义一个可以接受任意类型的类

11 篇文章 1 订阅

C++定义一个可以接受任意类型的类, 可以在虚函数使用

定义一个模板类就可以接受任意类型, 但是虚函数和模板是不能一起使用的.

template<typename A>
void Func(const A& a) {
    std::cout <<"Func(const A& a) : "<< a << std::endl;
}

编译器在编译期间,会检查代码中哪些地方使用了这个函数,例如,如果在整个程序中使用到了两种类型:Func<int>(9); Func<float>(9.3); 编译器会生成两份函数的二进制代码:void Func(const int& a),以及void Func(const float& a)。

由于对于类的虚函数来说,其是否被调用是在程序运行的时候才知道,因此编译阶段不知道需要生成几份函数。 例如,基类是Base,有两个子类A和B, 代码中使用基类的指针来调用子类的虚函数 ,在编译阶段并不能知道调用的是哪个子类的虚函数,因此,编译器不知道类A和B中的模板函数被调用的情况,因此,不知道需要生成几份函数。

每个含有虚函数的类中都有一个虚函数表,该虚函数表存储着该类的所有的虚函数的地址,因此,虚函数为模板函数时,该表的大小是不知道的,因此编译器禁止! 虚函数为模板函数的情况下,编译阶段不能确定类的虚函数表的大小原因:下文有提到"However, the number of instantiations of a member function template is not fixed until the entire program has been translated". 例如,一般一个类定义在一个单独的文件中,编译器编译这个文件时并不知道其他文件对该类的virtual func的调用情况,所以无法确定模板虚函数的实例化个数!

我们可以使用 OOP 中继承的思想来实现: Data类中定义两个类, 组成一个继承关系, 子类使用模板来接受任意类型参数, 我们就可以在Data类中定义一个基类的智能指针, 进而可以获取子类的任意数据, 如果仅仅使用一个子类, 那么在定义 std::unique_ptr<Derive<T>> val_; 就会出现错误因为没有 T 类型.

所以我们的做法就是定义一个Data类, Data类中声明两个类, 两个类是继承关系, 子类使用模板, 可以接受任意类型数据, Data类成员是一个智能指针并指向基类, 我们就可以通过基类来构造或访问子类的任意类型数据.

//Data类型: 可以接受任意数据的类型
class Data
{
public:
	Data(const Data&) = delete;
	Any& operator=(Data&) = delete;

	//这个构造函数可以让Data类型接受任意其他类型的数据
	template<typename T>
	Data(T data)
		: base_(std::make_unique<Derive<T>>(data))
	{

	}

	//这个方法能把Data对象里面存储的data数据提取出来
	template<typename T>
	T cast()
	{
		//通过dynamic_cast将指针由基类指针转为子类指针
		Derive<T>* pd = dynamic_cast<Derive<T>*>(base_.get());
		if (pd == nullptr)
		{
			throw "The type passed in is incorrect!";
		}
		//返回子类中保存的任意类型的数据
		return pd->data_;
	}
private:
	//基类类型
	class Base
	{
	public:
		virtual ~Base() = default;
	};
	//派生类类型
	template<typename T>
	class Derive : public Base
	{
	public:
		Derive(T data) : data_(data)
		{

		}
	public:
		T data_;
	};
private:
	// 定义一个基类指针 
	std::unique_ptr<Base> base_; //如果没有基类,定义std::unique_ptr<Derive> base_;会出现错误,因为Derive需要一个T类型
};

测试

int main()
{
	/*Dataa("hello");
	std::cout << a.cast<std::string>() << std::endl;*/
	Data a(123);
	std::cout << a.cast<int>() << std::endl;
	Data b(std::string("123"));
	std::cout << b.cast<std::string>() << std::endl;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值