static_cast转换指针仅限于有继承或隐式转换关系的类型间,支持上行转换、受控下行转换及void*双向转换,但无运行时检查,多重继承偏移不修正,误用将导致未定义行为。

static_cast转换指针的基本规则
static_cast 可以在相关类型之间转换指针,但仅限于存在明确继承关系或可隐式转换的指针类型之间。它不做运行时检查,也不处理多重/虚继承下的偏移修正(那是 dynamic_cast 的事)。用错时编译器可能不报错,但运行时行为未定义。
- 只能用于:
- 向上转型(子类指针 → 父类指针),安全且常用
- 向下转型(父类指针 → 子类指针),不安全,需确保实际指向子类对象
-
void*与其他指针类型之间的双向转换(但不能跨 cv 限定符混用)
- 不能用于:
- 无关类型间的转换(如
int<em></em>→char),编译失败 - 去除
const(该用const_cast)
- 无关类型间的转换(如
向下转型时为什么容易出错
父类指针转子类指针看似简单,但static_cast完全信任你——它不验证对象真实类型。如果父类指针实际指向的是纯父类对象,或指向的是另一个子类实例,转换后解引用就会导致未定义行为(常见崩溃、数据错乱)。
- 示例风险场景:
Base* pb = new Base(); // 不是 Derived 对象 Derived* pd = static_cast<Derived*>(pb); // 编译通过,但 pd 是悬空指针 pd->derived_method(); // 未定义行为
- 更隐蔽的问题:多重继承中基类子对象地址可能与完整对象地址不同,
static_cast不自动调整偏移,而dynamic_cast会
什么时候该用 static_cast 而不是 dynamic_cast
当你 100% 确定类型关系且追求零开销时,static_cast 是合理选择。典型场景包括:
- 模板元编程中已通过
std::is_base_of等静态断言确认继承关系 - 工厂函数返回
Base*,但调用方明确知道构造的是哪个派生类(例如配置固定、单例初始化完成) - 在性能关键路径(如游戏循环、高频回调)中避免 RTTI 开销
- 转换
void*(如从malloc或 C API 接收的内存)到具体类型指针
注意:static_cast 无法将 const Base<em></em> 转为 Base;若需修改 const 对象,必须用 const_cast,且前提是原对象本身非 const。
立即学习“C++免费学习笔记(深入)”;
void* 和 const 限定符的组合陷阱
static_cast 允许 void<em></em> ↔ T,但对 cv 限定符极其敏感:
-
static_cast<int<em>>(vp)</em>✅(void→int*) -
static_cast<const int<em>>(vp)</em>✅(void→const int*) -
static_cast<int<em>>(c_vp)</em>❌(const void→int*,编译失败) -
static_cast<const int<em>>(c_vp)</em>✅(const void→const int*)
常见错误是把 const void<em></em> 直接强转成非 const 指针,误以为和 C 风格一样宽松。C++ 的类型系统在这里更严格,绕过它需要两步:先 const_cast<void>,再 static_cast<int*> —— 但这通常说明设计有问题。
向下转型和 void* 转换是 static_cast 指针操作中最易埋雷的地方,尤其在跨模块或遗留 C 代码集成时,类型假设稍有偏差,问题就出现在运行时而非编译期。


















