Skip to content
Lesson 13 of 15

Step 1 of 7 · Reading · ~3 min

Learn

Classes, Inheritance, and Templates

Classes and Constructors

By the end of this lesson you can write a small C++ class that keeps its data private, sets that data up in a constructor, and answers questions about itself through const member functions.

A class bundles data with the functions that use it

A class is a type you define. Its variables are data members; its functions are member functions (methods). Here is a clock time that knows how many minutes past midnight it is:

#include <iostream>

class ClockTime {
    int hours;              // private: only ClockTime's own code sees these
    int minutes;
public:
    ClockTime(int hh, int mm) : hours{hh}, minutes{mm} {}
    int minutesSinceMidnight() const { return hours * 60 + minutes; }
    bool isOnTheHour() const { return minutes == 0; }
};

int main() {
    ClockTime lunch{12, 30};
    ClockTime alarm{7, 0};
    std::cout << lunch.minutesSinceMidnight() << "\n";   // 750
    std::cout << alarm.isOnTheHour() << "\n";            // 1
    return 0;
}

Trace lunch: the constructor stores hours = 12, minutes = 30; 12 * 60 + 30 is 750. You call a method with a dot: lunch.minutesSinceMidnight(). Inside the method, hours means this object's hours, so alarm and lunch each answer with their own data.

A bool printed with << shows 1 or 0. To print words, choose them yourself: std::cout << (alarm.isOnTheHour() ? "on" : "off").

public and private

Members of a class are private by default: main cannot write lunch.hours = 99;, it will not compile. The public: label opens everything after it to outside code. Keep data private and expose methods. A struct is the same thing with public as the default; that is the only difference.

The constructor and its initializer list

A constructor has the class's name and no return type. It runs once, when the object is created. The part after the colon, : hours{hh}, minutes{mm}, is the member initializer list: each member is built directly from the given value before the body {} runs.

The trap is naming a parameter the same as a member and assigning in the body:

ClockTime(int hours, int minutes) {
    hours = hours;       // assigns the PARAMETER to itself
    minutes = minutes;   // the members are never set
}

This compiles. The members keep whatever garbage was in memory, so minutesSinceMidnight() might print -858993460 instead of 750. The initializer list avoids it: in hours{hh} the name before the brace is always a member.

Once you write any constructor, the compiler no longer gives you a free zero-argument one: ClockTime t; stops compiling.

const member functions

The const after () in int minutesSinceMidnight() const promises the method does not change the object. The compiler holds you to it (minutes++ inside it is an error), and only const methods may be called on a const ClockTime&, the parameter style you learned for passing objects without copying. Mark every method that only reads as const.

Operator precedence inside methods

* binds tighter than +. hours * 60 + minutes is right; hours + minutes * 60 is a different number. When a formula needs the sum first, write the parentheses: 2 * (a + b) is not 2 * a + b. For a = 1, b = 7 the first is 16, the second is 9.

Common mistakes

  • Missing parentheses: writing the doubled sum without brackets gives 9 instead of 16 for a 1 by 7 rectangle. A hidden test uses exactly that shape.
  • Self-assignment in the constructor: assigning a parameter to itself because it shares the member's name leaves the member uninitialized, so area prints a garbage number. Use the initializer list.
  • Printing the bool directly: streaming a bool prints 1 or 0, not yes or no.
  • Wrong comparison: a square check that returns true for any non-zero sides fails on 9 1; and 0 0 has equal sides, so it is a square.

Your exercise

Write the Rectangle class: two private int members, a constructor using an initializer list, and three const methods area(), perimeter() and isSquare(). The starter reads the two numbers and has the print lines waiting for the class. Watch the parentheses in the perimeter.

Up nextInheritance and Virtual FunctionsClasses, Inheritance, and Templates

Discussion

Ask a question, share an insight, or help someone who’s stuck.

Sign in to post a comment or reply.

Loading…