9.1. Classes And Objects

Time: 00:06:12 | Download: Large, Large (CC), Small | Streaming, Streaming (CC) | Slides (PDF)
Review

"Object-oriented modeling and design is a way of thinking about problems using models organized around real-world concepts. The fundamental construct is the object, which combines both data structure and behavior in a single entity" (Rumbaugh et al., 1991, p. 1). Rumbaugh's first sentence underscores one of the many strengths of the object-oriented paradigm: it is both a way of looking at software problems and a way of implementing software solutions to those problems. Today, object-oriented practitioners typically call the data structure and behavior attributes and operations, respectively. The language of object-orientation forms a bridge that spans the entire software development process, joining together analysis, design, and programming (often abbreviated OOA, OOD, and OOP, respectively.)

The object-oriented paradigm or model is based on three essential concepts: encapsulation, inheritance, and polymorphism. We'll study the latter two in subsequent chapters. But encapsulation is just a synonym for an object, and Rumbaugh's second sentence provides our initial definition:

Encapsulation

"Object-oriented programming languages support encapsulation, thereby improving the ability of software to be reused, refined, tested, maintained, and extended. The full benefit of this support can only be realized if encapsulation is maximized during the design process" (Wirfs-Brock & Wilkerson, 1989, p. 71).

Encapsulation combines attributes and operations (i.e., data structure and behavior) into an entity we call an object. Furthermore, objects isolate and protect the data from the application or client program (the code that uses the object). Objects allow the application to access or use its attributes (data) through a stable, controlled public interface formed by the class's public operations (functions).

Classes describe objects with the same attributes and operations. A common metaphor is to think of a class as a cookie cutter and the individual objects as the cookies. The cookie cutter defines each cookie's size, shape, and decoration. We can use the cookie cutter to stamp out as many cookies as we want, and each cookie will have the same size, shape, and decorations as the others. However, we eat the cookies but not the cookie cutter; similarly, objects do the work in a program. Rumbaugh et al. (1991) collectively refer to attributes and operations as features. Encapsulation, the first defining characteristic of the object-oriented paradigm, combines attributes and operations into an object that controls the visibility and access to those features.

C++ programmers call attributes and operations member1 variables and functions, respectively. Like all variables, member variables have a type and a name. Similarly, member functions have a name, a parameter list (that might be empty), and (except constructor functions) a return type.

Attributes

Attributes are the values saved in an object. Ideally, each attribute is a quality or characteristic inherent in something - some aspect whose value helps distinguish between different class instances. For example, a class named Person might have the attributes:

Every object instantiated from Person will have these attributes. C++ implements attributes as member variables declared in a class. The compiler allocates memory for the variables inside the objects instantiated from the class. So, the attribute values saved in one object are independent of those saved in any other - some, none, or all the values may be the same.

Operations

Operations represent the services an object can provide to an object-oriented program. Operations correspond to member functions in a C++ program. Recall that C++ is a hybrid language, meaning it supports "regular" functions unrelated to classes and functions that are part of a class. Fortunately, everything we have learned about functions applies to member functions: they have a header (the return value type, the function name, and the argument list) and a body. Of course, member functions also have properties related to object orientation that we will discover in this chapter.

Classes can define four kinds of operations (or functions in C++)

  1. Constructors and destructors (create and destroy objects)
  2. Access (gets or sets private data values)
  3. Algorithmic (performs useful calculations with an object's data)
  4. Helper (often private, implements common operations from other member functions)

Class Responsibilities

Ward Cunningham introduced CRC cards (class-responsibility-collaboration) in the early days of industrial object-oriented software development. (See Fowler, 2004, pp. 62-63.) CRC cards consist of index cards on which the developers write the name of a class, its responsibilities, and the names of other classes with which it collaborates. Moving the cards around while discussing various ways a program can use a class helps the developers determine where (in which class) to place attributes and operations. When developers place an attribute or operation in a class, they are saying in effect that the class is responsible for maintaining the data or providing the operation or service. Thinking in terms of "responsibilities" becomes increasingly helpful as the number of classes in a program and their interconnections grow.

Feature Visibility

C++, like Java, controls the visibility of class features with a set of keywords (in order of increasing visibility): private, protected, and public. Although the C++ syntax is a little different than Java, the meanings of the keywords are the same in both languages, as summarized by the following Venn diagram.

A Venn diagram illustrating the private, protected, and public keywords. 'Private' restricts access to class scope; 'protected' extends access to subclasses, and 'public' allows access from all program parts.
C++ feature visibility conceptualized as a Venn diagram. Note that the effects of these keywords are at the class level rather than at the object level. The effect is especially significant when using the private keyword. The private features of objects instantiated from different classes are mutually inaccessible, while objects instantiated from the same class may access each other's private features unrestricted. See the Time and Fraction demonstrations later in this chapter for examples.

C++ Class Specifications

C++ classes differ in two important ways from Java classes. First is the obvious difference in how they use the public and private (and later the protected ) keywords. The features in a Java class are individually declared as public or private. Alternatively, in a C++ program, regions within the classes are labeled as public or private. Second, Java always includes method bodies inside the class. C++ programs can define short member functions inside of a class (and doing so makes them inline functions, without the need to use the inline keyword), but programmers should only prototype larger functions in the class and write the bodies in a separate compilation unit (i.e., another .cpp file). For example:

class Time
{
	private:
		int	hours;
		int	minutes;
		int	seconds;

	public:
		Time();
		Time(int h, int m, int s);
		Time(int s);

		Time	add(Time t2);
		Time*	add(Time* t2);

		void	print();
		void	read();
};
A C++ class specification. All the features included in a class specification are said to be members of the class, which results in two important terms:
Member variables
Variables defined in class-scope. For example: hours, minutes, and seconds.
Member functions
Functions defined in class-scope. For example: add, print, and read. Three functions, all named Time, are constructors (introduced later in the chapter) and are also members of the Time class.

Class And Object Summary

Although the above class is a simple example, there are several important observations we can make:


1 You may see some variation in terminology between different authors. Historically, authors called the variables declared in a class either member variables or static variables (covered in detail later in the chapter). Alternatively, some authors call all variables declared in a class member variables and categorize them as either instance variables or class variables (also detailed later). I learned and used the first terminology as a professional software engineer. Furthermore, static or class variables are uncommon. Consequently, I use the first terminology throughout the text but explicitly state when I'm discussing static or class variables. The variations also apply to functions, although less commonly.


Fowler, M. (2004). UML distilled: A brief guide to the standard object modeling language. Boston: Addison-Wesley.

Rumbaugh, J., Blaha, M., Premerlani, W., Eddy, F., & Lorensen, W. (1991). Object-Oriented Modeling and Design. Englewood Cliffs, NJ: Prentice Hall.

Wirfs-Brock, R.; Wilkerson, B. (1989). "Object-oriented design: a responsibility-driven approach." Conference Proceedings on Object-Oriented Programming Systems, Languages and Applications. OOPSLA 1989 Proceedings, October, 1-6.