Exercise: Compile and run print_test. Ask questions.
Object Oriented Programming (OOP) on the other hand allows computer scientists to create objects that can both store information like a variable, but also manipulate information like a function. An object is a variable, but with a special type. Each object is an instance of some class. All objects of a particular class have similar behavior, but can store different data values.
Question: What might be some examples of classes/objects?
The general format of a class declaration is:
class <class name> { private: // private members, typically the data public: // public members, typically the methods // a method is just a function inside a class }; // This semicolon is requiredC++ uses private, public, and protected (ignore the last one for now, to control access to elements of a class. Public methods and data are accessible to anyone using the class, while private methods can only be used internally in the class.
C++ methods fall into four primary types:
Question: Can a method be of more than one of the types listed above?
Let's look at the example class in cs35/class/w02-oop/point. point.h is a header file. It describes the name and method signatures of the Point class, but does not say how the these methods are implemented. point.cpp implements the methods in the Point class. testpoint.cpp uses code from the Point class to run some basic tests. Let's see how these pieces fit together.
Preprocessor, compiler, linker, make
Exercise: Add a deposit method. Note you will need to modify both .h and .cpp files. Test your changes.
bool BankAccount::deposit(float amount) { if (amount < 0 ) { return false; } balance += amount; //Where is balanced defined? return true; }
cd ~/cs35/classes/w02-oop/person/ [person]$ ls faculty.cpp Makefile person.h student.h testPoly.cpp faculty.h person.cpp student.cpp testInherit.cpp [person]$ make g++ -c person.cpp g++ -c student.cpp g++ -c faculty.cpp g++ -o testInherit person.o student.o faculty.o testInherit.cpp g++ -o testPoly person.o student.o faculty.o testPoly.cpp
For now, ignore the keyword virtual. We'll use it a bit later.
In this example, the Person class is a base class, because other classes Student and Faculty build off of this base. Student and Faculty are derived classes.
Question: How do we inform the Student class that it should be derived from the Person class. What evidence is there in the .h header file? What about the .cpp source file?
Question: How can we call a base method from a derived class?
Exercise: Write code in testInherit.cpp to answer the questions at the end of the file and explore the relationship of derived and base classes. Discuss.
Exercise: Try writing your own derived class. You will need a .h and a .cpp file. You will also need to modify the Makefile to compile your new code. Add changes to testInherit.cpp to test your new class. Don't forget the #include. You may need to add the .o file to your Makefile to properly link your new class into testInherit.
Alright, we put dynamic memory off long enough, it is time to dive into one of the more confusing topics of learning C++. But we have some motivation. There are some things we haven't fully explained so far.
int* x; //a pointer to an int int *y; //same int* w, z; // w is a pointer to an int, z is an int. Person* p; // A pointer to a person objectPointers can give us more control over the use of memory in a program. Every pointer is just an address. Addresses are all the same size (8 bytes or 64 bits these days). For most objects, a pointer to an object is much smaller than the object itself. We can delay allocating space for an object until we need to use it. Objects are dynamically allocated using the new operator. Objects allocated by new must be de-allocated eventually using delete. Failure to delete dynamically allocated data results in a memory leak. Leaks are frowned upon.
int* arry; //A pointer to the start of an array Person* p; arry = new int[20]; //dynamically allocate a new array of 20 ints p = new Person("Terrelle", 21); p->print(); delete p; //delete an object delete [] arry; //delete an arrayPointers can also be used to make changes to variables in functions visible outside the scope of the function. Look at pointers.cpp in cs35/class/w02-oop for some examples. Note that if we have an object or base type, we can get the address of that object using the & operator. If x is a foo type, then &x is a pointer to a foo object. If p is a pointer to a foo object (type foo*), then *p is the object (of type foo) pointed to by p.
Exercise: examine the code in pointers.cpp what are the types of all the expressions in the first block of printfs, e.g., what is the type of q, *q, and *(&i)?
Exercise: Look at the two swap functions. How are they different? Why does one work and the other one break? Keep in mind that in this course, C++ functions are always pass by value. What are the types of each value passed into each function?
Look at class/w02-oop/person/testPoly.cpp to see how pointers are used with objects. Note that we can call a method directly on a pointer to an object using the -> notation. Note the use of new and delete. We'll discuss the virtual bit if we have time on Thursday, or in lab on Friday.
It takes time to get used to pointers. Feel free to ask plenty of questions.