c++constructorvirtual-functionsstdbind

Why does invoking a virtual method in constructor and binding a virtual method then calling it later yield different results?


This is my code snippet:

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();
}

The output is:

base foo
derived foo

foo() prints base foo, because at this point, the vtable still points to Base::foo, according to answers under this question.

During the construction of Base, the object is not yet of Derived class. So, when calling std::bind() the this pointer is still a pointer to the Base class, and the argument pointer is passed in the constructor body of Base, so why does p->fn call foo in the Derived class?

My compiler is Apple clang version 14.0.3


Solution

  • when called std::bind is still a pointer to Base class, and the argument pointer is passed in constructor body of Base, why p->fn called foo in derived class?

    Once your Derived constructor is called, every pointer to the Base is now a pointer to Derived. The vtable accessed from that location is now a Derived vtable

    That's the "dynamic" part of dynamic dispatch.