Good cop/bad cop interview - 2nd phase

Welcome back,

If you may miss the first part, you can read it Good cop/bad cop interview - start.

Good cop - I'm sure you don't have that C++ labelled bullet in your leg! These codes were tricky but not for you!

Bad cop - Yes, because you do not figure it out without a compiler!

Good cop - That not true. I knew those.

Bad cop - Liar.

Good cop - Don't start to piss me of again Bad cop!

Bad cop - Stop lying!

After all, here we again. Our brave admissions are fight again, unsure the job applicant, discredit the company! This is the time to stop them and get back to some more tricky examples!

#include <iostream>

int main()
    unsigned c = 2004;
    const int &d = c;
    std::cout << "c value: " << c << std::endl;

    c = 2012;

    std::cout << "c value: " << c << std::endl;
    std::cout << "d value: " << d << std::endl;

Bad cop - Ahm... the output?

The evil within is the unsigned int => ref int. This is only works when we declare our integer reference as const. This let happen an implicit conversion in the background from unsigned integer to signed integer. For this step there is a hidden memory allocation to hold the converted value of c for the reference of d. Passing method parameters as const references may do this trick (implicit conversion) behind.

Bad cop - But what we really love in C++ is the following: (Bad cop show some empathy and enthusiasm, but be sensible!)

#include <iostream>

class Base
    Base() {std::cout << "Base()\n";}
    ~Base() {std::cout << "~Base()\n";}
    Base(const Base&) {std::cout << "CopyBase\n";}

class Derived : public Base
    Derived() {std::cout << "Derived()\n";}
    ~Derived() {std::cout << "~Derived()\n";}
    Derived(const Derived& other) {std::cout << "CopyDerived\n";}

    Base* create(Base g)
        return new Derived();

int main()
    Derived d;

    Base* g = d.create(Base());
    delete g;

    return 0;

Bad cop - what about an output?

Good cop - yes that would be nice!

(Thanks God, they agree on something for the first time! :)

This example tries to figure out that the applicant knows how virtual destructor works. (Or at least knows what could happen when it's missing?!) This example is good as the parameter static and dynamic type is clear. We have a variable d, which type is Derived. This variable created on the stack and freed when we run out of its scope. The ctor and dtor call is obvious - Base() -> Derived() when destroyed -> ~Derived() -> ~Base().

But we create a g variable where the static type is Base, but the dynamic type is Derived! That's okay, but when the destructor called by the delete, then only ~Base() gets called, because it's destructor is not virtual! There is no virtual table, so there's no chance to know where to go when destructing g.

(While our brave cops do not check this code with a compiler, they forget to ask about the Derived class copy construct missing explicit Base class initialization. ;)


We may continue... (With our experiences)

Date modified: 
Thursday, December 15, 2016 - 17:00
Date published: 
C++, Interview, Example