Larry Jing
Larry Jing

Reputation: 404

Copy constructor and assignment operators with polymorphism

Just failed an interview because of this, and I'm still confused:

class A
{
public:
    A(int a) : a_(a) {}
    
    // Copy constructor
    
    // Assignment operator
    
private:
    int a_;
};
 
class B : public A
{
public:
    B(int a, int b) : A(a), b_(b) {
    }
    
    // Copy constructor
    
    // Assignment operator
    
private:
    int b_;
};

How do you implement the copy constr/assignment op, and why does the constructor of B have to have an A initialized in the initializer list? It doesn't work if it's not in the list.

Upvotes: 0

Views: 315

Answers (2)

user4581301
user4581301

Reputation: 33942

How do you implement the copy constr/assignment op

Trick question, I think. In this case the best option is to do absolutely nothing. Neither class contains (and owns) any resources requiring more than the default special member functions. Observe the Rule of Zero.

Some style guides recommend explicitly defaulting special member functions. In this case

class A
{
public:
    A(int a) : a_(a) {}
    
    A(const A &) = default;
    A& operator=(const A &) = default;
    
private:
    int a_;
};

may be appropriate.

why does the constructor of B have to have an A initialized in the initializer list?

All class members and base classes must be fully constructed before entering the body of a constructor.

B(int a, int b) 
{ // Entering constructor's body. A must be constructed before we get here.
}

A has no default constructor, so the constructor it does have must be explicitly called in the initializer list to construct the base class before the construction of B can proceed.

Addressing comment

A's copy constructor and assignment operator are trivial:

A(const A & src): a_(src.a_)
{

}

A& operator=(const A & src)
{
    a_ = src.a_;
    return *this;
}

B is a bit trickier because it also has to make sure A is copied

B(const B & src): A(src), // copy the base class
                  b_(src.b_)
{

}

B& operator=(const B & src)
{
    A::operator=(src); // assign the base class by explicitly calling its 
                       // assignment operator
    b_ = src.b_;
    return *this;
}

Note: If I were hiring, I'd take the programmer who called me out on the trick question over the programmer who did the extra work and risked an unforced error.

Upvotes: 2

john
john

Reputation: 87957

why does the constructor of B have to have an A initialized in the initializer list?

A only has one constructor which takes an int. B has A as a base class, which means that every B object must first construct an A object. How else are you going to construct that A object with it's required parameter except by using an initialiser list?

Upvotes: 2

Related Questions