|
| Wednesday, January 18, 2005 |
| Classes and Objects |
Overview
- Classes are essentially C structures with functions inside
- Objects are instances of classes, created much the same way you create instances of a struct in C.
- The classes become essentially new data types and the object names become new variables of that data type.
- The data members are the internal data that defines the object's current state
- Classes support information hiding, often called data encapsulation.
- The functions inside a class, often also called methods, now define the behavior of the data.
- The parameters of the functions, often also called messages, provides the communication with other objects
Class definitions and syntax
- classes have a simplified syntax derived from C structures, but more powerfulExample struct in C
struct rectangle
{
int width, height;
};or
typedef struct
{
int width, height;
} Rectangle;is now defined as:
class Rectangle
{
public:// functions will go here
private:
int width, height;
};
- you do not need the struct keyword or need to typedef
- The data declarations inside a class are called "data members", just like a C struct, or more often "instance variables". Try to use the preferred term "instance variable".
- Always capitalize the names of classes. Good C++ style.
- Always put the class definition into a .h header file.
Creating objects
- Creating objects from a class, also called instances of the class, is the same as creating instances of a struct.Example (in the .h file):
class Rectangle
{
public:// functions will go here
private:
int width, height;
};Note: ending semi-colon (leaving out the semicolon is a very common error)
(in the .C file):
main()
{
Rectangle box;
...
}- Note that the class name, Rectangle, is used just like a new data type, and the object name, box, is a variable of that data type.
Features of classes (the same as structs)
- Classes can be used as array types
- Objects can be passed to functions
- Objects can be returned by functions
- Pointers can be used to access objects
Additional features (C++ specific)
- Syntax features that allow information hiding (that is what the public: and private: are all about)
- Can include functions (also called methods) leading to "smart data", or "data that has behaviors"
- Syntax features for conveniently initializing and cleaning up objects (using constructors and destructors, see below)
- The functions can protect the data (data encapsulation, see below)
Information hiding
- No other piece of code should be able to change the data inside an object directly. It must always go through functions to alter the data.
- The values of a data at any time in the program are the "state" of the object at that time
- The functions can protect the state of the object, and make sure that the data is always correct.
- An object with logically correct data is called a "consistent" object.Example: A Rectangle object should never have a negative height or width.
3 levels of information hiding:
private:
- usually used for the data in the class
- accessible only by functions (methods) within that class
- cannot be accessed by other classes or objectsprotected:
- we will talk about this when we get to Inheritance in a later classpublic:
- accessible by any other code
- usually used only for methods (functions)
Notes
- private:, protected:, public: are optional
- By default, all members are private: unless otherwise specified
- private:, protected:, public: can be placed in any order and can be included more than once
- Good practice: put a public: at the top of the class definition, followed by the constructor, destructor, and function definitions, then a private: followed by the data member definitions. However, some professional programmers like to put all the private: data at the top of the class.
Method definitions
- Methods are used to protect access to the data, and give behavior to the data, that is make the data "smart".
- Method definitions are nearly identical to C, except for the following concepts:
Put the prototype inside the class definition in the .h file
class
Rectangle
{
public:
void setWidth(int);
void setHeight(int);
int getWidth();
int getHeight();
int calcArea();
private:
int width, height;
};
Put the function definitions the .C file, just as in C, but precede the function name with the class name and two colons
void Rectangle::setWidth(int w)
{
if (w >= 0)
width = w;
}
void Rectangle::setHeight(int h)
{
if (h >= 0)
height = h;
}
int Rectangle::getWidth()
{
return width;
}
int Rectangle::getHeight()
{
return height;
}
int Rectangle::calcArea()
{
return width * height;
}
-
Notice that the variable
w
in the first function definition is a formal parameter that is local to the
function definition only. The variable
width
is the instance variable of the class. The instance variable will hold its
value after the function ends, long after the parameter has disappeared.
Data Encapsulation
- Methods are used to protect access to the data, and
give behavior to the data.
- Notice that the first two
functions will not allow the instance variables
width
and
height
to be set to negative values.
- What happens if
setWidth
is called with the parameter
w
as
a negative value?
- The state of the object, that is the values in
the instance variables, can never be corrupted with inappropriate or illogical
values. The object is "tough".
Using the methods you have defined
- Just write a standard function call, but now
you must put an object name and a dot in front of the function name:
objectname.functionname(param1, param2, ...);
Example:
box.setWidth(13);
- Notice that the object name and the dot are the same syntax you use for structs, except now you can put a function name after the dot, in addition to an instance variable name.
- The following program creates a box and a square, and prints the areas:
#include <iostream>
#include "Rectangle.h"
using namespace std;
int
main()
{
Rectangle
box, square;
box.setWidth(10);
box.setHeight(20);
square.setWidth(12);
square.setHeight(12);
cout <<
"The area of a box of width " <<
box.getWidth() << " and height " <<
box.getHeight() << " is " <<
box.calcArea() << "." << endl;
cout <<
"The area of a square of width " <<
square.getWidth() << " and height "
<<
square.getHeight() << " is " <<
square.calcArea() << "." << endl;
return 0;
}
- Method calls inside the main program must always have the object name and dot before the method name.
- Inside a the definition of a function, it can call other functions inside the same class without an object name or dot. These method calls look just like C function calls.
- Instead of "call the area function" and send it a struct Rectangle, we tell each Rectangle object to compute its own area!
- Reinforces object-oriented design, information hiding, and data encapsulation.
- Our Rectangle objects are independent, self-contained entities, whose data can not be corrupted!
Constructors and Destructors
- Constructors and destructors are special methods that are used to initialize the object, and to clean up the object just before it goes away.
- Constructors have the same syntax as any other function except they have the following two restrictions:1. They have no return type at all, not even void
2. They must have the exact same name as the class name- Constructors are used to initialize the instance variables inside the class.
- In good object design, you always initialize all instance variables to logical values when the object is constructed. This means the object always starts in a consistent, logical state.
- The constructor with no parameters is called the "default" constructor.
- Constructors can also be written with parameters. These are usually overloaded functions. Overloaded functions are functions with the same name but a different number of parameters, or different data types for the parameters, or a different order of the data types in the parameters..
- If you don't write any constructors at all, the compiler will write a default constructor with an empty pair of curly braces, {}. If you write any constructors, with any parameters, then the compiler will only use the constructors you write.- Destructors are exactly like constructors, except they have two additional restrictions:
1. They have a tilde character, ~, in front of their name.
2. They can have no parameters, although they must have the empty parentheses, (). Therefore they cannot be overloaded, and there can be only one destructor, the default destructor.- Destructors are often just empty functions, because they are usually used for releasing resources such as files or memory allocations, which is done only in specific types of classes.
- Destructors are optional, but some C++ experts say you should write one anyway, even if it is empty. The compiler will write a default, empty destructor for you if you don't write it.
Constructor example -- in the .h file:
class Rectangle
{
public:Rectangle(); // default constructor
Rectangle(int, int); // overloaded constructor
~Rectangle(); // destructorvoid setWidth(int);
void setHeight(int);
int getWidth();
int getHeight();
int calcArea();private:
int width, height;
};
Constructor definitions the .C file:Rectangle::Rectangle(int h, int w)
{
setHeight(h);
/* has the same effect as:
if (h > 0)
height = h;
else
height = 0;
*/
setWidth(w);
/* has the same effect as:
if (w > 0)
width = w;
else
width = 0;
*/
}
Rectangle::Rectangle()
{
height = 0;
width = 0;
}
Rectangle::~Rectangle()
{
}
- The default constructor is now called when the object is declared. This is a hidden function call, that is not directly apparent in the C++ code.
- Notice the constructors initialize the instance variables in much the same way the setHeight and setWidth functions do. It is often smart to call the setHeight and setWidth functions from within the constructors. It is usually better to call a function than to duplicate its code in another function.
- Now our objects always have logical values no matter how they are created. If the programmer does not set the height and width with setHeight and setWidth, the default constructor will set the height and width to 0.
- Now lets use the overloaded Constructor to initialize our objects. Notice the parentheses and parameters in the object declaration. An object declaration is a constructor call. Always.#include <iostream>
#include "Rectangle.h"using namespace std;
int main()
{
Rectangle box(10, 20);Rectangle square(12, 12);
cout << "The area of a box of width " <<
box.getWidth() << " and height " <<
box.getHeight() << " is " <<
box.calcArea() << "." << endl;cout << "The area of a square of width " <<
square.getWidth() << " and height " <<
square.getHeight() << " is " <<
square.calcArea() << "." << endl;return 0;
}
Readings
Deitel and Deitel, 6.6 - 6.9 .
| Back to Csc 125 Programming in C++ |
| Scott Badman Office: B132 Phone: 353-2250 sbadman@parkland.edu |
Parkland College, 2400 W. Bradley Avenue, Champaign, IL 61821 |