Read an Excerpt
From Chapter Eight: Structuring Your Data Using Classes
This chapter is about creating your own data types to suit your particular problem. This will go beyond the notion of collecting related variables together in a data structure that we saw in the last chapter. It is also about creating objects, the building blocks of object-oriented programming. An object can seem a bit mysterious to the uninitiated but, as we shall see in this chapter, an object is just an instance of one of your own data types.
In this chapter you will learn about:
- Classes and how they are used
- The basic components of a class and how a class is declared
- Creating and using objects of a class
- Controlling access to members of a class
- Constructors and how to create them
- The default constructor
- References in the context of classes
- The copy constructor and how it is implemented
Before we get into the language, syntax and programming techniques of classes, we'll start by considering how our existing knowledge relates to the concept of classes.
So far, we've learnt that C++ lets you create variables which can be any of a range of basic data types: int, long, double and so on. In the previous chapter, you saw how you could use the struct keyword to define a structure which, in turn, defined a variable representing a composite of several other variable types.
The variables of the basic types don't allow you to model real-world objects (or even imagine objects) adequately. It's hard to model a box interms of an int, for example. However, as we saw in the previous chapter, you could use the members of a struct to define extended attributes of your object. You could define variables, length, breadth and height to represent the dimensions of the box and bind them together as members of a Box structure, as follows:
With this definition of a new data type called Box, you can go ahead and define variables of this type just as you did with variables of the basic types. You can then create, manipulate and destroy as many Box objects as you need to in your program. This means that you can model objects using structs and write your programs around them. So--that's object-oriented programming all wrapped up then?
Well, not quite. You see, object-oriented programming (OOP) is based on a number of foundations (famously encapsulation, polymorphism and inheritance) and what we have seen so far doesn't quite fit the bill. Don't worry about what these terms mean for the moment--we'll be exploring that in the rest of this chapter and throughout the book.
The notion of a struct in C++ goes far beyond the struct in C--it incorporates the object-oriented notion of a class. This idea of classes, from which you can create your own data types and use them just like the native types, is fundamental to C++, and the new keyword class was introduced to describe this concept. The keywords struct and class are almost identical in C++, except for the access control to the members, which we will find out more about later in this chapter. The keyword struct is maintained for backwards compatibility with C.
We saw a little of what structs can do in the last chapter. In this chapter, we'll be looking at classes, and we'll see how much more we can do. Let's look at how we'd define a class for boxes:
Just like when we defined the Box structure, when we define CBox as a class we are essentially defining a new data type. The only differences here are the use of the keyword class instead of struct, and the use of the keyword public followed by a colon that precedes the definition of the members of the class. These are called data members of the class, since they are variables that store data.
We have also called the class CBox instead of Box. We could have called the class Box, but MFC adopts the convention of using the prefix c for all class names, so we might as well get into the habit now. MFC also prefixes data members of classes with m_ to distinguish them from other variables, so we'll use this convention too.
The public keyword is a clue as to the difference between a structure and a class. It just defines the members of the class as being generally accessible, in the same way as the members of the structures that we used in the last chapter were. The members of a struct, however, are public, by default. As you'll see a little later in the chapter, though, it's also possible to place the accessibility of the class members.
We can declare a variable, bigBox say, that is an instance of the CBox class like this:
This is exactly the same as declaring a variable for a struct, or indeed for any other variable type. Once we've defined the class CBox, the declaration of variables of this type is quite standard. The variable bigBox here is also referred to as an object or an instance of the class CBox.
The notion of class was invented by an Englishman to keep the general population happy It derives from the theory that people who knew their place and function in society would be much more secure and comfortable in life than those who did not. The famous Dane, Bjarne Stroustrup, who invented C++, undoubtedly acquired a deep knowledge of class concepts while at Cambridge University in England and appropriated the idea very successfully for use in his new language.
Class in C++ is similar to the English concept, in that each class usually has a very precise role and a permitted set of actions. However, it differs from the English idea, because class in C++ has largely socialist overtones, concentrating on the importance of working classes. Indeed, in some ways it is the reverse of the English ideal, because, as we shall see, working classes in C++ often live on the backs of classes that do nothing at all.
Operations on Classes
In C++ you can create new data types as classes to represent whatever kinds of objects you like. As you'll come to see, classes (and structures) aren't limited to just holding data; you can also define member functions or even operations that act between objects of your classes using the standard C++ operators. You can define the class CBox, for example, so that the following statements work and have the meanings you want them to have:
if(box1 > box2) // Fill the larger box
You could also implement operations as part of the CBox class for adding, subtracting or even multiplying boxes--in fact, almost any operation to which you could ascribe a sensible meaning in the context of boxes.
We're talking about incredibly powerful medicine here and it constitutes a major change in the approach that we can take to programming. Instead of breaking down a problem in terms of what are essentially computer-related data types (integer numbers, floating point numbers and so on) and then writing a program, we're going to be programming in terms of problem-related data types, in other words classes. These classes might be named CEmployee, or CCowboy, or CCheese, or CChutney, each defined specifically for the kind of problem that you want to solve, complete with the functions and operators that are necessary to manipulate instances of your new types.
Program design now starts with deciding what new application-specific data types you need to solve the problem in hand and writing the program in terms of operations on the specifics that the problem is concerned with, be it CCoffins or CCowpokes.
Let's summarize some of the terminology that we will be using when discussing classes in C++:
- A class is a user-defined data type.
- Object-oriented programming is the programming style based on the idea of defining your own data types as classes.
- Declaring an object of a class is sometimes referred to as instantiation because you are creating an instance of a class.
- Instances of a class are referred to as objects.
- The idea of an object containing the data implicit in its definition, together with the functions that operate on that data, is referred to as encapsulation.
A class is a data type that you define. It can contain data elements which can either be variables of the basic types in C++, or other user-defined types. The data elements of a class may be single data elements, arrays, pointers, arrays of pointers of almost any kind, or objects of other classes, so you have a lot of flexibility in what you can include in your data type. A class can also contain functions which operate on objects of the class by accessing the data elements that they include. So, a class combines both the definition of the elementary data that makes up an object and the means of manipulating the data belonging to individual objects of the class.
The data and functions within a class are called members of the class. Funnily enough, the members of a class that are data items are called data members and the members that are functions are called function members or member functions. The member functions of a class are also sometimes referred to as methods, but we will not use this term in this book...