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:

libc++abi.dylib: Pure virtual function called!
Program ended with exit code: 9

Program output.

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:

Item #9 From Effective C++.

Related discussion: C++ corner case: You can implement pure virtual functions in the base class.

5 Replies to “Interview question, part 3”

  1. The “why” in this question is that C++ is more type safe than languages like Java and C# with respect to object construction. There is no possibility, as in those languages, of accessing not yet initialized stuff down in the most (or more) derived class.

    More that’s wrong with the code: in class

    Derived

    the keywords

    public

    and

    virtual

    are superfluous and should be omitted. Also the

    final

    keyword should probably be omitted, it’s wrong as a default. The arguments to

    main

    are declared but not used, and may cause undesired warning diagnostics.

    main

    returns

    1

    , which in practice is OK but indicates failure, and is not a standard-supported value. I think these issues are more serious, since they’re usually not diagnosed by the compiler or runtime support.

    After all, source code is mostly about communicating to humans, and all that redundant stuff just distracts.

    1. I disagree regarding the keywords. They more explicitly state the intent of the programmer. I know from the compiler stand point they’re not needed, but I like to put them in my code to quickly see, for example, that the derived class overrides a virtual function, inherits publicly from Base, etc, etc. But I guess we’re really discussing style at this point 🙂

        1. I think it helps the newcomers to C++ see the stated intent more clearly. I agree that non of those keywords are needed, but how many new C++ developers know for example that the only difference between

          struct

          and

          class

          is the default visibility? I personally prefer ALL keywords that can be in place to be in place. But again, we’re really discussing style, not validity of code.

          1. Nobody has mentioned that Base does not have a virtual destructor.

Leave a Reply to Alf P. SteinbachACancel reply