Introduction to Programming with C++
Intro to C++ Classes
Objectives
- Learn how to define your own class in C++.
Important Definitions
- constructor, accessor fucntion, mutator function, member variables, member functions, dot notation
Classes Introduction
We have learned that Bjarne Stroustrup developed the C++ language to improve upon C, but so far we have not yet learned much about the differences between these two languages. A simple answer to this implicit question is that C is basically a subset of C++; in other words, most C programs will run when compiled with a C++ compiler, but the reverse is not true. Unlike C, C++ is an object-oriented language, where the data in the program is conceptually grouped together with the functions that work on the data. In this assignment, we will begin to experiment with object-oriented programming.We learrned last time that you can create your own compound types in C++, using two mechanisms: structures and classes. Classes are the biggest difference between C and C++ because it is with a class that one can create an object, the basis of "object-oriented programming." In fact, one of the earliest names for C++ was C with Classes.
One of the most important programming structures in C++ is called a class. In most object-oriented programming languages such as C++, a class is a user-defined type that includes both
- a set of member variables associated with it,
- as well as a set of member functions.
Note that the C structure or "struct" that we saw in our previous assignment only includes a set of variables but does not have any functions contained in it. However, the idea of including member functions make intuitive sense. For example, a "time" structure should correspond to the way people record the time of day, and the operations we defined correspond to the sorts of things people do with recorded times. Similarly, a "point" structure could correspond to the mathematical concept of a point, and operations such as calculating the distance between the two are important and should be closely associated with it.
Member functions of a class differ from the other C++ functions in only two main ways:
- When we call a member function, we will invoke it on a specific class object. People sometimes describe this process as "performing an operation on an object," or "sending a message to an object."
- The member function is declared inside the class definition to make the relationship between the class and the function explicit.
Structures versus Classes
We will see how to convert a structure into a class.Consider the following code that would not only store time but also display it:
- a structure that could handle times
// Define a structure that records the minutes, hours and seconds for
// a time period
struct Time {
int hour, minute;
double second;
}; - a function that could print times:
// A function that takes as input a Time structure and outputs the time
// stored in it.
void printTime(Time mytime) {
cout << mytime.hour << ":" << mytime.minute << ":" << mytime.second << endl;
}
Time, we would have to pass currentTime
as an argument to the printTime(...) function:
Time currentTime = { 9, 14, 30.0 }; // Create and initialize the time data
|
Time that includes
a member function called print(...) that does the exact same thing.
- The first step is to change the name of the function from
printTime(...)(that is currently independent of any classes) toTime::print(). The scope resolution operator,::, is between the name of the class from the name of the function, linking theprint()function to theTimeclass object. - The second step is to realize that we no longer need the
myTime parameter because
print()is a member function of the class that contains the data (the member variables).Conceptually, you are switching from asking a function to print something, which you give as input, to asking an object to "print itself". This function will no longer have a parameter named myTime but will refer to the object as current object. The kind of member variable access seen in the
print()member function is called implicit because the name of the class object does not appear in the member function explicitly. Features like this are one reason member functions are often more concise than other functions. - Finally, note here that this function is not supposed to change anything,
to we can indicate that fact by adding the keyword "
const" after the paramters list (which in this case is empty).
class Time { |
class Time { |
Time is similar to declaring
a struct.
Once you have that object, you can invoke the print() function on that object:
Time currentTimeObject; // currentTimeObject refers to an object of time Time |
Constructors
There are two ways to give values to the member variables in structures or classes. One way we have already encountered is to initialize when you declare the the structure:
Time testTime = {9, 14, 30.0}; // initial values of 9 hours, 14 minutes, 30.0 seconds
|
If Time is a structure, we can give use a makeTime(...)
function to take as input the number of seconds and create a Time
structure with the appropriate values:
// This function takes as input a positive number and splits |
In the case of classes, the corresponding function is so common that there is a special syntax for these constructors, which looks like:
Time::Time(double secs) { |
- The constructor must have the SAME
NAME AS THE CLASS, and no return type
because the instance variables of the class are modified in the function.
When we assign values to hour,
minute and second,
the compiler implicitly knows we are referring to the instance variables of the
object because the scope resolution operator indicates this connection.
Alternatively, we can refer to the new object---the one we are constructing---inside the constructor function with the keyword this:
The changes are indicated in red.Time::Time(double secs) {
this.hour = int(secs / 3600.0);
secs -= this.hour * 3600.0;
this.minute = int(secs / 60.0);
secs -= this.minute * 60.0;
this.second = secs;
} - There is no need to declare a local variable for a new time object as in the case with the function that worked with structures; this function is referring to the member variables automatically.
Initialize or Construct?
We initializeTime structures using curly-braces:
Time bedTime = { 3, 35, 0.0 };
|
Time bedTime(seconds); |
Time and calls the constructor, passing the value of
seconds as an argument.
The system allocates space for the new object and the constructor
initializes its instance variables.
We can certainly overload the constructor so that declaring and initializing
an object of type Time looks similar to the way we did with
the struct variable.
The function can be declared in the class definition and defined elsewhere
as follows:
class Time { |
To invoke this constructor, we use the same syntax as before, except that the arguments have to be two integers and a double:
Time currentTime(9, 14, 30.0); |
Classes and Objects
To reiterate class is a definition of an object. A class resembles a struct with the formal difference being the following: only that all struct members are public by default while all classes members are private.In practice, however, most people use a struct when they are just creating a compound type, while they use a class when they want that compund type to have associated member functions as well as member variables.
The simplest definition of a class is:
class classname{
// members
} Here is an example of a small class which we will discuss in the classroom:
/* This is a small example of a class */
#include <iostream>
#include <cstdio>
using namespace std;
class Ebook{
public:
Ebook(int numpages) ; // Constructor
void setBookmark( int currentplace) ;
int getCurrentPage( );
private:
int pageCount;
int currentPage;
};
int main() {
cout << "Let's create a new e-book named mybook with 128 pages." <<endl;
Ebook mybook(128);
cout << "Let's create a new e-book named newbook with 100 pages." <<endl;
Ebook newbook(100);
cout << "Next let's set a bookmark in mybook at 56 pages." <<endl;
mybook.setBookmark(56);
cout << "Next let's look at where the bookmarks are." <<endl;
cout << "Current Page in mybook: " << mybook.getCurrentPage() << endl;
cout << "Current Page in newbook: " << newbook.getCurrentPage() << endl;
return 0;
}
Ebook::Ebook(int numpages) {
pageCount = numpages; //These assign the parameters to the member variables.
currentPage = 1;
}
void Ebook::setBookmark(int currentplace) {
currentPage = currentplace; }
int Ebook::getCurrentPage( ) {
return currentPage;
}
Assignment Specifics
This assignment must be done individually, but you are encouraged to converse.
- Define a new class for a type called
CounterType. An object of this type is used to count things, so it records a count that is a non-negative whole number. This means the class needs a private member varaible calledcounter. - Include a default constructor which sets the counter to 0.
- Include a second constructor with one arguement which sets the counter to the value specified in the arguement.
- Include a public member function called
incrementwhich increases the count by 1. - Include a public member funciton called
decrementwhich decreases the count by 1, but does not allow the count to become negative. - Include a public "accessor" member function called
getcountwhich returns the curent count. - Include a public member function called
writecountwhich outputs the count to the screen. - Create a driver main which tests all of the member functions.
Be sure to also do the following:
- Include comments for any parts of the code that is non-intuitive to let us know what that portion does.
- Include a descriptive header as a comment at the top of your source code
as follows:
// Course: CSC 226 Introduction to Programming with C++
// Name: Your Name (or both names if you are working with a partner)
// Assignment 13: <Put a brief sentence about your program here.>
/*
Purpose: <Put a more in-depth description of the program here.>
*/
