You are on page 1of 21

Monday December 3rd, 2001 Agenda 1. Fill out class evaluation forms 2. Project #7 questions 3.

friends continued: friend classes 4. The “this” pointer and classes 5. Static member functions 6. Simple dynamic memory allocation: “the heap” 7. Dynamic memory allocation+classes 8. Review for the final

Friend classes class CPerson { public: CPerson(int age) { m_age = age; } void HowOldAreYou(void) { cout << "None of your business!\n"; } private: int m_age; void take_shirt_off() { cout << “OK.”; } }; main() { CPerson carey(30); carey.HowOldAreYou(); cout << carey.m_age; carey.take_shirt_off(); } When should you use friend classes? // error! // error!

doc. } private: friend class CDoctor. You look OK.m_age > 120) cout << "You're probably sick!\n".”. } void HowOldAreYou(void) { cout << "None of your business!\n". // our friend class Cdoctor { public: void GiveExam(CPerson &pers) { if (pers.take_shirt_off(). main() { CPerson carey(30). void take_shirt_off() { cout << “OK. pers. CDoctor doc. cout << "No boils. int m_age. } }.\n".GiveExam(carey).class CPerson { public: CPerson(int age) { m_age = age. } . } }.

b. . b. } . cout << &b << endl..printmyaddress().. // we can do this… cout << &a << endl. main() { SomeClass a.printmyaddress(). }. float m_var2.The this pointer Question: how can an instance of a class determine its own address? Class SomeClass { public: void printmyaddress() { // what do I write here? } private: int m_var1. // but what about this? a.

m_y. cout << "My x value is: " << this->m_x << endl. m_y = y.PrintMyAddress().How do we find our address? With “this” class Point { public: Point(int x. How can we use “this”? . int y) { m_x = x.m_y << endl. }. }. }. main() { Point a(5. a. cout << "My y value is: " << (*this). void PrintMyAddress(void) { cout << "I am at: " << this << endl. } int GetX() const { return m_x. } Questions: 1. int GetY() const { return m_y.6). } private: int m_x. What does “this” point to? 2.

Point b(3. } . Point::PrintMyAddress(&b). a.PrintMyAddress(). int x2 = b. int x = Point::GetX(&a). Point::PrintMyAddress(&a). int x2 = Point::GetX(&b). int x = a.2). } C++ pulls a trick on you.4). Point b(3.GetX(). What’s really happening is the following: main() { Point a(1.PrintMyAddress().GetX(). b.4).2).How does calling member functions really work? When you call a class member function: main() { Point a(1.

cout << "My y value is: " << (*this). but it shows what really happens under the hood) .m_y << endl. m_y. } int GetY(Point *this) { return(this->m_y). cout << "My x value is: " << this->m_x << endl. } void PrintMyAddress(Point *this) { cout << "I am at: " << this << endl.The first (hidden) argument to every class member function is the address of the instance variable. C++ does this automatically without telling you! It’s as if we defined our class as follows: class Point { int GetX(Point *this) { return(this->m_x). (the above is not valid code. }. } private: int m_x.

” . m_y += dy.this continued When you access a member variable from a member function: void ShiftPoint(int dx. int dy) { m_x += dx. } You are implicitly using the this pointer to get to the actual instance data: void ShiftPoint(Point *this. this->m_y += dy. but for now. int dx. instead it’s passed in each time a member function is called. int dy) { this->m_x += dx. We’ll learn more about this next quarter. } Note: The “this” pointer is not a part of the object’s member data. this is all you have to know about “this.

We can have static member functions too! A static member function is one that only refers to static member variables or NO member variables in a class. static string m_dream.Static member functions Remember that static class member variables are shared across all instances of a class class CAmerican { . // shared dream }.. . string CAmerican::m_dream = “The American dream”. Static member variables can NOT refer to non-static member variables.. private: string m_name.

string CAmerican::m_dream = "The american dream". // shared dream // note: no static here! void CAmerican::MyDream(void) { cout << m_dream << endl. private: string m_name.MyDream(). static string m_dream.Defining a static member variable class CAmerican { public: static void MyDream(void). // shared dream }. a. Do static member functions have a this pointer? 2. } Questions: 1. How else can you call static member functions? . } main() { CAmerican a.

it may be called without actually referring to an instance! Static member functions do NOT get an implicit this parameter like non-static member functions. STATIC MEMBER FUNCTION: void CAmerican::MyDream(void) { cout << m_dream << endl.Another way to call static member functions: main() { CAmerican::MyDream(). } NON-STATIC MEMBER FUNCTION: void CAmerican::PrintMyName(CAmerican *this) { cout << this->m_name << endl. } . } Since MyDream does not access any member variables.

We can do this by using dynamic memory allocation! struct Foo { int a. float c. it is placed on the stack. ptr->c = 3. delete ptr. main() { Foo *ptr. ptr = new Foo. // when we’re done .. Sometimes. // allocate ptr->a = 1..Dynamic Memory Allocation As we know. }. we want to create a new variable. DoSomethingWithIt(ptr). . every time we declare a local variable. but we don’t want it to be stored on the stack.

When you’re done with the memory. ptrvariable = new Type.new: the new command is used to allocate new memory. The delete command is used to free memory allocated by new. ptr = new int.718. YOU MUST DELETE EVERYTHING YOU NEW! . delete ptr. Usage: Type *ptrvariable. or float *foo = new float. you can access it via the pointer that was returned to you: *foo = 2. Example: int *ptr. use the delete command. *ptr = 10. Once the memory is allocated.

*pg = *pf. pg = new float. // sized array! pi[5] = 10. *pf = 3.14159. cout << *pg. delete pf. int *pi = new int[n]. cin >> n. delete[]pi. cout << pi[5]. float *pg. } main() { int n. } // [] for array! .Other examples: main() { float *pf = new float. delete pg.

// not random! cout << *pi. pi = new int. It returns NULL if not enough memory is available. // random! } } . It’s random just like local variables. you are requesting that the operating system allocate a new chunk of memory for you. } else { cout << pi. The memory allocated by new is not automatically initialized. The new statement returns a pointer to this new memory. cin >> n.When you use the new statement. if (pi == NULL) { cout << “Out of memory!\n”. main() { int n. int *pi.

this is what happens: 1. When you delete a class.Neg(). this is what happens: 1.6). } When we use new to allocate a class. to initialize it. The constructor for the class is called on this memory. The memory is released to the operating system. The destructor for the class is called 2.We can use new to allocate room for new classes too! main() { // allocs mem & calls constructor point *ptr_to_pt = new Point(5. // done with it! . Memory is allocated 2. delete ptr_to_pt. (*ptr_to_pt). cout << ptr_to_pt->GetX().

. } ~CHarryPotter() { cout << "I die thinking of " << m_thought. }. // . } .. main() { CHarryPotter *ptr. } private: string m_thought.class CHarryPotter { public: CHarryPotter(string thought) { m_thought = thought. delete ptr. cout << "I am born\n". ptr = new CHarryPotter( "Bertie Botts Beans").

. cout << sizeof(ptr). ptr = new CStupidClass[3]. How does construction/destruction work? What happens if we forget the [] in delete? . m_for_fun = 0. // ??? // . }.. } private: int m_for_fun.Can we allocate an array of classes? class CStupidClass { public: CStupidClass(void) { cout << "Created\n". delete[] ptr. } ~CStupidClass() { cout << "Destroyed\n". 2. main() { CStupidClass *ptr. } Question: 1.

} . ptr = new CHarryPotter[50].What about an array of Harry Potter classes? class CHarryPotter { public: CHarryPotter(string thought) { m_thought = thought. // BAD! // . } ~CHarryPotter() { cout << "I die thinking of " << m_thought. } private: string m_thought.. cout << "I am born\n". delete [] ptr. }.. main() { CHarryPotter *ptr.

Question: Why can’t we allocate an array of Harry Potters? .

'A'}. // 'A'. // free! } private: Student *m_pStudents. m_cur. }. int m_size. char grade. m_cur = 0. m_size = max_size. } ~CS32() { delete [] m_pStudents. m_cur++. // 10 slots } section1. class CS32 { public: CS32(int max_size) { m_pStudents = new Student[max_size]. // current roster size } bool AddStudent(Student &st) { if (m_cur == m_size) return(false). // 1 of ten . 'B' etc }. main() { Student a = {"Carey".AddStudent(a). CS32 section1(10). m_pStudents[m_cur] = st.struct Student { char name[10].