I was given this piece of code to analyze and point out what’s wrong with it:
struct Base
{
Base() { bar(); }
virtual void foo() = 0;
void bar() { foo(); }
};
struct Derived final : public Base
{
virtual void foo() override {}
};
int main(int argc, char** argv)
{
Derived d;
return 1;
}
I was also able to compile and execute this program on my Mac; output from Xcode gives away the answer:
Program output:
libc++abi.dylib: Pure virtual function called!
Program ended with exit code: 9
But why? The constructor of Base
calls void bar()
, which in turn calls pure virtual void foo() = 0
. The Derived
overrides foo()
so what’s the problem here?
Inside the constructor of Base
, the type of this
pointer is… Base
. So the call to foo()
inside bar()
resolved to Base
version of foo()
, which is a pure virtual function lacking implementation. This is illegal and the compiler puts a check inside Base::foo()
virtual function table pointing to __cxa_pure_virtual
. That in turn calls __pthread_kill
terminating the program.
__cxa_pure_virtual disassembly
libc++abi.dylib`__cxa_pure_virtual:
0x7fff723e8730 <+0>: pushq %rbp
0x7fff723e8731 <+1>: movq %rsp, %rbp
0x7fff723e8734 <+4>: leaq 0x1f2f(%rip), %rdi ; "Pure virtual function called!"
0x7fff723e873b <+11>: xorl %eax, %eax
0x7fff723e873d <+13>: callq 0x7fff723dc14a ; abort_message
Update
Related discussion: C++ corner case: You can implement pure virtual functions in the base class.