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

static_cast转换至动态类型非基类的运行原理及代码疑问解析

C++ static_cast 工作机制与代码行为解析

先看你提供的代码及输出:

代码

#include <iostream>
using namespace std;

class A {
public:
    virtual void f() const { cout << " A::f "; }
    virtual void g() { cout << " A::g "; }
    virtual A* n() { cout << " A::n "; return this; }
    virtual void t() { cout << " A::t "; }
};

class B: public A {
public:
    virtual void f() const { cout << " B::f "; }
    void g() { cout << " B::g "; A::n(); }
    A* n() { cout << " B::n "; return this; }
    void t() { cout << " B::t "; }
};

class C: public A {
public:
    virtual void f() { cout << " C::f "; }
    void g() const { cout << " C::g "; }
};

int main() {
    A* q2 = new B(); 
    A* q3 = new C();
    (static_cast<C*>(q2))->g(); cout << endl;
    (static_cast<C*>(q2))->t(); cout << endl;
    (static_cast<B*>(q3->n()))->f(); cout << endl;

    return 0;
}

输出

C::g 
 B::t 
 A::n  A::f

下面逐个分析关键语句的行为:


1. (static_cast<C*>(q2))->g();

  • q2 是指向 B 对象的 A* 指针,static_cast<C*>(q2) 属于非法的交叉转换:B 和 C 是 A 的平行派生类,无继承关系,这种转换本身是未定义行为(C++标准不保证任何结果)。
  • 输出 C::g 的原因:A 的 g() 签名是 void g(),而 C 的 g() 是 void g() const,两者签名不同,不属于虚函数重写,只是同名重载。当通过 C* 指针调用 g() 时,编译器会进行静态绑定,直接生成调用 C::g() 的机器码,完全忽略指针实际指向的是 B 对象。这种结果是不可靠的,换个编译器或环境可能有不同表现。

2. (static_cast<C*>(q2))->t();

  • t() 是 A 中声明的虚函数,B 重写了它,C 没有重写(继承自 A 的 t())。
  • 虚函数的调用是动态绑定,只看指针实际指向的对象类型,和指针被强制转换后的类型无关。这里 q2 实际指向 B 对象,所以调用 B::t(),输出 B::t。
  • 注意:虽然这里转换本身还是未定义行为,但虚函数的动态绑定机制让结果看起来符合预期,本质上仍是危险的操作。

3. (static_cast<B*>(q3->n()))->f();

  • 第一步:q3 是指向 C 对象的 A* 指针,调用 n()。C 没有重写 A 的 n(),所以调用 A::n(),输出 A::n,并返回指向 C 对象的 A* 指针。
  • 第二步:static_cast<B*>(...) 又是非法的交叉转换(C 对象转成 B*),属于未定义行为。
  • 第三步:调用 f()。A 的 f() 是 virtual void f() const,B 重写了该签名的函数,而 C 的 f() 是 void f()(签名不同,不属于重写)。因此 C 对象的虚函数表中,f() const 对应的仍是 A::f()。动态绑定后,调用 A::f(),输出 A::f。

关键总结

  • static_cast 是编译期转换,不会做运行时类型检查:只要编译器认为类型转换语法合法(比如派生类和基类之间的转换),就会生成转换代码,完全不管实际对象的真实类型。
  • 当转换涉及无继承关系的平行类时,属于未定义行为,结果不可预测。
  • 虚函数的调用由实际对象的类型决定,和指针的静态类型无关;非虚函数则由指针的静态类型决定,直接绑定到对应类的函数。

内容的提问来源于stack exchange,提问作者matteo camillo

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 17:35:14