2
class A{
virtual void setEnable(bool enable) = 0;
};

class B : A{
    B() {
        setEnable(true);
    }
    ~B() {
        setEnable(false);
    }
    bool enable_ = false;
    
void setEnable(bool enable) override {
    enable_ = enable;
}
};

Am I correct in understanding that the B :: setEnable function will be added to the vtable only after the constructor exits and this is undefined behavior?

Gogogo
  • 167
  • 1
  • 8
  • 1
    Side note: If you tried this in an `A` constructor you'd get the UB because no derived classes will have been fully initialized yet and `A` doesn't implement the function. – user4581301 Aug 18 '21 at 22:21

1 Answers1

5

Am I correct in understanding that the B::setEnable function will be added to the vtable only after the constructor exits and this is undefined behavior?

No. Inside the body of the A constructor, the A object is fully initialized, but the B object is not. The problem with calling a virtual function from a constructor is that it will unintuitively call the method of the same type that the constructor belongs to, without the polymorphic behavior.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
bolov
  • 72,283
  • 15
  • 145
  • 224
  • 2
    *Inside the body of the constructor the object is fully initialized.* can never be emphasized enough. Perhaps I should even have used ***bold** italics*. Not understanding this leads to a lot of silly bugs and inefficiencies. – user4581301 Aug 18 '21 at 22:07
  • But standard says: "If the virtual function call uses an explicit class member access ([expr.ref]) and the object expression refers to the complete object of x or one of that object's base class subobjects but not x or one of its base class subobjects, the behavior is undefined." Am I misunderstanding something in this wording? – Gogogo Aug 18 '21 at 22:38
  • @Gogogo The quote starts with "if". It's a special case where this sentence applies. Check the example in that paragraph. – bolov Aug 18 '21 at 23:00