CS 202 Fall 2013  >  Notes for Thursday, October 10, 2013

CS 202 Fall 2013
Notes for Thursday, October 10, 2013

Object-Oriented Programming: Introduction [15.1–15.5]

Object-Oriented Programming

Object-oriented programming (OOP) is a programming paradigm based on the following ideas.

In C++, polymorphism is enabled through the mechanisms of inheritance and virtual functions. We look at inheritance today and virtual functions next time.

Inheritance

Inheritance is a way of creating new classes from existing classes. Suppose we have a class X.

[C++]

class Y : public X {
    ...
};

This makes a new class Y based on X. We say that X is the base class, while Y is the derived class.

The “public” indicates what status the public members of X have in class Y. (We almost always use public inheritance, but C++ also has protected and private inheritance; look into those if you want.)

In fact, an object of type Y will contain an object of type X. The members of that X object may be used as if they are members of Y.

Inheritance should express an “is-a” relationship. For example, above we should be able to say that an X is a Y. A standard example of this involves kinds of shapes.

[C++]

class Shape {                    // Base class
    ...
};

class Triangle : public Shape {  // Derived class #1
    ...
};

class Square : public Shape {    // Derived class #2
    ...
};

class Circle : public Shape {    // Derived class #3
    ...
};

We would generally expect the above to work well, since a triangle is a shape, a square is a shape, and a circle is a shape.

Protected Members

Members that are public may be accessed by any function. Members that are private may be accessed only by functions that are either members or friends of the class. Even derived-class objects cannot access private members.

A third category is protected. These members are almost private; they can also be accessed by the derived class. In other words, protected members can be accessed by members and friends of the class and members and friends of derived classes.

Inheritance, Constructors, and Destructors

Recall that a derived-class object has a base-class object sitting in it. The base-class object is constructed before any derived-class constructor is executed. As with member constructors, we can pass parameters to base-class constructors. When we do this, we write as if a derived-class object has a member whose name is the base class.

[C++]

class X {
public:
    X(int a, const string & b)
        :_a(a), _b(b)
    {}
private:
    int _a;
    string _b;
};

class Y : public X {
public:
    Y(int a, const string & b, double c)
        :X(a, b),  // Pass a, b to base-class ctor
         _c(c)     // Pass c to member ctor
    {}
private:
    double _c;
};

Members and base-class objects will be destroyed in the opposite order from their creation. Since the base-class constructor is called before the derived-class constructor, the base-class destructor will be called after the derived-class destructor.

Redefining Base-Class Members

We can redefine a base-class member by making a derived-class member of the same name. This hides the base-class member.

However, we can still access the base-class member by prefixing its name with “BASE_CLASS::”.

[C++]

class X {
public:
    void print() const
    {
        cout << "X print" << endl;
    }
};

class Y : public X {
public:
    void print() const
    {
        cout << "Y print" << endl;
    }
};

int main()
{
    X x;
    Y y;

    x.print();     // Outputs "X print"
    y.print();     // Outputs "Y print"
    y.X::print();  // Outputs "X print"
}

Class Hierarchies

We can have many classes derived from a single base class. We can also derive new classes from these derived classes. All these classes together form a class hierarchy.

Typically, a class hierarchy has just two levels. We have a single base class from which all other classes are derived. We never create an object of the base class (indeed, we usually make the creation of such objects impossible, by making the base class abstract; more about this next time). Rather, we use the base class to specify an interface that the derived classes implement.

We create objects of the derived classes, but we use them as if they are base-class objects (we will cover how to do this next time, too).

For today’s lab work, see the 10/10 Challenge.


CS 202 Fall 2013: Notes for Thursday, October 10, 2013 / Updated: 10 Oct 2013 / Glenn G. Chappell