11/30/05 lecture notes for CISC181 Fall 2005 In the .cc file for a class, start with the function prototypes of the member functions that were NOT declared inline in the .h file. Then, put the class name followed by :: in front of each member function name. The purpose of a constructor is to give initial values to the private data members. It is "function overloading" that gives me the ability to to have more than one constructor; they all have the same name (i.e. the name of the class) but they take different number and types of parameters. Inside a member function, we can refer to the private data members,e.g. x and y, simply _as_ x, or y, e.g. inside void Print::print() const we simply write: cout << "(" << x << "," << y << ")"; Or we can use the "this" pointer. The "this" pointer always points to the object on which the member function is invoked. So for example, in the main we have: p.print(); that means that inside the print member function, for that call to p.print(), this is a pointer to the object p. So, this->x and x refer to the same value. this->y and y refer to the same value. Why would you do this? In a case like the print() member function you probably would NOT do this, except for emphasis. Sort of like saying I DO like ice cream, instead of just saying I like ice cream. Typcially to compile a program that uses a class, you need something like this: CC -c point.cc CC -c pointMain.cc CC point.o pointMain.o -o pointMain Now you can see why we like Makefiles so much! They take care of all that detail for us. The copy constructor is invoked via code like this: Point a(1,2); Point b(2,3); Point c(4,-1); Point p(a); Point q(b); Point r(c); What this does is make p a copy of a, q a copy of b, and r a copy of c. There are two kinds of copy constructor: (1) The kind created for you automatically by the compiler. (2) The kind you write yourself. If you don't create one yourself, the compiler ALWAYS creates one for you. The function prototype of the copy constructor is: Point(const Point &orig); Like all constructors, it cannot have a return type, and it cannot have "const" after the closing ")". The parameter is a const reference to a "source" object. I typically this "orig", but there is nothing sacred about that name. The kind the compiler creates for you ===================================== Uses "default memberwise copy" For example, in the case of the point class you get: Point (const Point &orig) { this->x = orig.x; this->y = orig.y; } Or equivalently, and more simply: Point (const Point &orig) { x = orig.x; y = orig.y; } Now consider the following class ================================ // hand.h // A class for a simplified card game // Simplifying assumptions: // * There are suits, but they don't matter to this game // * The values of cards are 1 through 10 // * Rather than abstract cards into a class, we'll just use an int // * a Hand is any number of cards // * We will use a linked list, but hide the fact that // a hand is a linked list in the private part of the Hand object class Hand { public: Hand() { head = NULL; } ; void addCard(int newCard); void removeCard(int CardToGo); bool cardIsInHand(int cardNum) const; int countCardsThatMatch(int cardNum) const ; int numCards() const ; ~Hand(); // return borrowed space to the heap. // suppose I DON'T implement my own copy constructor // so the compiler creates one for me with default memberwise copy // Hand(const Hand & orig); // copy constructor void print(void) const; // print member function private: struct CardNode_S { int value; CardNode_S *next; }; CardNode_S *head; }; Suppose I have a main program like this one: // testHand.cc // test the hand class .h file to make sure it compiles #include using std::cout; using std::endl; #include "hand.h" int main(void) { Hand x; x.addCard(3); x.addCard(2); x.addCard(5); cout << "result of x.print(): "; x.print(); // test the copy constructor Hand y(x); std::cout << "result of y.print(): "; y.print(); x.addCard(999); y.addCard(111); cout << "result of x.print() after adding 999: "; x.print(); cout << "result of y.print() after adding 111: "; y.print(); }