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

构造函数中调用虚方法与绑定后调用为何结果不同?

问题解析:构造函数中绑定虚函数为何最终调用派生类版本

代码片段

class Base {
  public:

  Base() {
    foo();
    bind();
  }

  virtual void foo() {
    std::cout << "base foo\n";
  }

  void bind() {
    fn = std::bind(&Base::foo, this);
  };

  std::function<void()> fn;
};

class Derived : public Base {
  public:

  void foo() override {
    std::cout << "derived foo\n";
  }

  void bind()  {
  }

  int val;    
};

int main() {
  Base* p = new Derived();
  p->fn();
}

输出结果

base foo
derived foo

疑问点

构造Base期间,对象尚未成为Derived实例,此时调用foo()输出base foo符合预期——因为构造基类时对象的动态类型是Base,虚表指向Base::foo。但构造时通过std::bind绑定了&Base::foo和this指针,为何后续调用p->fn()时会执行Derived::foo?


原因解析

  1. this指针的本质:在Base构造函数中,this的静态类型是Base*,但它实际指向的是Derived对象的基类子对象内存区域。std::bind保存的是这个指针的副本,最终指向的是完整的Derived对象。
  2. 虚函数的调用机制:你绑定的&Base::foo是一个虚函数的成员指针。对于虚函数,调用时不会直接固定调用基类版本,而是会根据对象的实际动态类型(即构造完成后的Derived类型)去查找虚表中的对应函数。
  3. 构造前后的动态类型变化:基类构造期间,对象的动态类型是Base,所以此时直接调用foo()会执行Base::foo;但当整个Derived对象构造完成后,对象的虚表已经切换为Derived的虚表,此时通过std::bind保存的this指针调用虚函数,就会触发Derived::foo的执行。

简单来说,std::bind并没有把调用固定在Base::foo上,只是保存了调用虚函数的入口和对象指针,最终调用哪个版本由对象构造完成后的实际类型决定。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 22:12:14