You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

《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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 15:40:23