CS 70

Reminder: Implementing a Class

Implementing the Cow and Barn Classes

Here's the implementation of our Barn class:

Barn::Barn() : cowCapacity_{1}, residentCow_{"Bessie", 42} {
    // Nothing (else) to do here!
}

Barn::Barn(size_t numCows) : cowCapacity_{numCows}, residentCow_{"Bessie", 42} {
    if (cowCapacity_ != 1) {
        throw std::invalid_argument("Barns can only hold one cow!");
    }
}

void Barn::feed() {
    residentCow_.feed();
}

You can explore this code by running it online (although you totally can, you don't need to look at the implementation of the Cow class).

  • Duck speaking

    In Java I just wrote all the code for my classes in one file. Why is it that we have to divide things into header files and implementation files?

  • Bjarne speaking

    It is how C did things in 1972.

  • Jo speaking

    Pfft!

  • Goat speaking

    Meh.

  • LHS Cow speaking

    But there is some sense in having a publicly viewable header file separate from the implementation file.

  • Goat speaking

    But we put some private details in our header file.

  • Bjarne speaking

    The header file isn't just for humans to read, it's for the compiler, too. Those details are things it needs to know.

  • Hedgehog speaking

    Can you go over the stuff with the :? I still don't know why we need that.

  • LHS Cow speaking

    The member-initialization list? We will!

Checking In…

Review the code for the Barn class (and, ideally, run it in Online GDB using the link above).

Why does the body of the default constructor have a comment saying there's “nothing (else) to do”?

Remember, C++ promises that when we hit the opening curly brace of the constrictor body, all the data members will have been initialized. It will either follow what we said in the class declaration itself (which, in our case, default-initialized all the data members), or we can override that behavior for specific data members using a member-initialization list.

In CS 70 (and in C++ code generally), it is considered bad style to perform assignment to data members in the body of a constructor when that initialization could have been done in a member-initialization list. It's wasteful to set an initial default value we don't actually want, and then immediately overwrite it with the actual value we do want.

In our code for the Barn class, since we are initializing all of the data members of the Barn instance in the member-initialization list, everything is set up and ready to go by the time we get to the body of the constructor, so there's no more set-up work to do.

  • Duck speaking

    So why have a body to the constructors at all?

  • LHS Cow speaking

    Good question! There are times when we can't do all the set up we want in the member-initialization list. Plus, sometimes you want to check things to make sure everything is okay, or produce debugging output.

  • RHS Cow speaking

    You can see those last two examples in our classes here, and we'll see the “more set-up” case soon.

(When logged in, completion status appears here.)