《C++设计模式实战》类型擦除示例疑问:为何用void*而非T*
为什么类型擦除示例中deleter要用void而非直接T?
你这个问题问到了类型擦除设计的核心——统一抽象层的通用性。原书里用void而非直接T,原因主要有两点:
1. 基类必须脱离具体类型,才能实现统一存储
如果像你修改的那样,把deleter_base的apply参数设为T*,那这个基类就会绑定到具体的T类型上——每个不同的T(比如int、std::string)都会生成完全独立的deleter_base<T>类型。这就意味着,你没法用一个通用的deleter_base*指针来指向不同类型的deleter子类对象,因为它们的基类类型根本不一样。
类型擦除的核心就是用一个不依赖具体类型的抽象基类,把不同类型的实现细节“擦除”,让上层代码可以统一处理。而void*作为无类型指针,刚好能让deleter_base成为一个完全通用的非模板基类,所有具体的deleter子类都能继承它,实现统一存储和调用。
2. 适配更灵活的类型擦除场景
假设你需要实现一个能存储任意类型对象的容器(比如类似std::any的智能指针版本),或者需要支持智能指针的向上转型(比如从SmartPtr<Derived>转到SmartPtr<Base>),用void*的设计就能轻松应对:
- 子类
deleter可以在apply里把void*安全转换回自己对应的T*(因为只有它知道真正的类型),保证正确调用析构函数或自定义删除器; - 基类不需要关心具体要删除的是什么类型,只需要负责调用
apply即可,完全实现了类型细节的隐藏。
举个反例:如果用你修改后的代码,当你想把SmartPtr<Derived>的删除器传给SmartPtr<Base>时,因为deleter_base<Derived>和deleter_base<Base>是不同类型,根本没法兼容,直接就会编译报错。
内容的提问来源于stack exchange,提问作者m_ognjen
相关产品推荐
相关产品推荐

