dis3

dis3 - CS32 Discussion Section 2C Week 4 TA: Brian...

Info iconThis preview shows page 1. Sign up to view the full content.

View Full Document Right Arrow Icon
This is the end of the preview. Sign up to access the rest of the document.

Unformatted text preview: CS32 Discussion Section 2C Week 4 TA: Brian Choi Reminder •  Homework 2 –  Due 2/1 Tuesday –  On stacks and queues Inheritance •  The process of deriving a new class using another class as a base. •  Our example: Dog Cat Features of a dog Features of a cat •  But there might be some common features in the two… Inheritance •  The process of deriving a new class using another class as a base. •  Our example: Animal Implement common features of all animals here derive derive Dog Cat Implement features specific to dogs here Implement features specific to cats here Deriving a class from another class Animal { public: Animal(); ~Animal(); int getAge() const; void speak() const; private: int m_age; }; base class •  Dog inherits Animal. class Dog : public Animal { public: Dog(); ~Dog(); string getName() const; void setName(string name); private: string m_name; }; derived class Deriving a class from another getAge(), speak() m_age setName(), getName() m_name Dog d1; d1.setName("puppy"); d1.getAge(); d1.speak(); Animal Dog Animal a1; a1.speak(); a1.setName(“abc”); Deriving a class from another •  What’s inherited: –  all member functions except the overloaded assignment operator (operator=), constructors, and the destructor –  all member variables •  However, the derived class cannot access the private members of the base class directly (e.g. Dog cannot access m_age). •  class D : public B –  a D object is a kind of B –  a D is a B (a Dog is an Animal) Construction •  So, a Dog is an Animal. What happens when we construct a Dog? •  1. The base part of the class (Animal) is constructed. Animal m_age 0 Construction •  So, a Dog is an Animal. What happens when we construct a Dog? •  2. The member variables of Dog are constructed. m_age m_name Animal 0 “” Construction •  So, a Dog is an Animal. What happens when we construct a Dog? •  3. The body of Dog’s constructor is executed. m_age m_name Animal 0 Initialized Construction •  Suppose I want to overload Dog’s constructor to create: Dog(string initName, int initAge); •  How would I go about implementing it? m_age m_name Animal 0 Initialized Construction •  Suppose I want to overload Dog’s constructor to create: Dog::Dog(string initName, int initAge) : m_age(initAge), m_name(initName) {} m_age m_name Animal 0 Initialized Construction •  Suppose I want to overload Dog’s constructor to create: Dog::Dog(string initName, int initAge) : Animal(initAge), m_name(initName) {} class Animal { Animal public: m_age Initialized Animal(int initAge); ... m_name Initialized }; Construction •  What is the difference between the two implementations here? Dog::Dog(string initName, int initAge) : Animal(initAge), m_name(initName) {} vs. Dog::Dog(string initName, int initAge) : Animal(initAge) { m_name = initName; } Destruction •  •  •  •  Just reverse the order of construction. 1. The body of destructor is executed. 2. The member variables are removed. 3. The base part of the class is destructed. class A { public: A() { cout << "A()" << endl; } A(int x) { cout << "A(" << x << ")" << endl; } ~A() { cout << "~A()" << endl; } }; class B { public: B() { cout << "B()" << endl; } B(int x) : m_a(x) { cout << "B(" << x << ")" << endl; } ~B() { cout << "~B()" << endl; } private: A m_a; }; class C : public A { public: C() : A(10), m_b2(5) { cout << "C()" << endl; } ~C() { cout << "~C()" << endl; } private: B m_b1; B m_b2; }; int main() { C c; } construction 1.  Base 2.  Members 3.  Constructor destruction class A { public: A() { cout << "A()" << endl; } A(int x) { cout << "A(" << x << ")" << endl; } ~A() { cout << "~A()" << endl; } }; class B { public: B() { cout << "B()" << endl; } B(int x) : m_a(x) { cout << "B(" << x << ")" << endl; } ~B() { cout << "~B()" << endl; } private: A m_a; }; class C : public A { public: C() : A(10), m_b2(5) { cout << "C()" << endl; } ~C() { cout << "~C()" << endl; } private: B m_b1; B m_b2; }; int main() { C c; } A(10) A() B() A(5) B(5) C() ~C() ~B() ~A() ~B() ~A() ~A() Overriding member functions •  Assume speak() is implemented as follows. void Animal::speak() const { cout << “...” << endl; } •  Dog inherits this function. •  But we want our Dog to really say something when ordered to speak!  Overriding member functions class Dog : public Animal { public: Dog(); ~Dog(); string getName() const; void setName(string name); void speak() const; private: string m_name; }; void Dog::speak() const { cout << “Woof!” << endl; } Animal a1; a1.speak(); •  Output … Dog d1; d1.speak(); •  Output Woof! Overriding member functions class Dog : public Animal { public: Dog(); ~Dog(); string getName() const; void setName(string name); void speak() const; private: string m_name; }; void Dog::speak() const { cout << “Woof!” << endl; } •  Why do we call this overriding, not overloading? Overriding member functions class Dog : public Animal { public: Dog(); ~Dog(); string getName() const; void setName(string name); void speak() const; private: string m_name; }; void Dog::speak() const { cout << “Woof!” << endl; } •  Why do we call this overriding, not overloading? •  Overload – same function name, but different return type and/or different set of arguments •  Override – same function name, same return type, same everything, except defined again in the derived class. Overriding member functions •  Can I still call the base class’s speak() on a Dog object? •  Yes, just do: Dog d1; d1.Animal::speak(); Virtual functions: Motivation •  Back to this diagram: Animal Implement common features of all animals here derive derive Dog Cat Implement features specific to dogs here Implement features specific to cats here •  Suppose we have speak() overriden in Cat, where it goes Meow! ; Virtual functions: Motivation •  C++ allows a pointer to the base class to point to a derived class. •  What do you think pAni ­>speak(); will do? should do? Animal *pAni; int x; cin >> x; switch (x) { case 1: pAni = new Dog; break; case 2: pAni = new Cat; break; default: pAni = new Animal; break; } Virtual functions: Motivation •  What it will do: … , no matter what x is. •  What it should do: Woof! if x == 1, Meow! if x == 2, … otherwise •  We want the overriden function to be called! Animal *pAni; int x; cin >> x; switch (x) { case 1: pAni = new Dog; break; case 2: pAni = new Cat; break; default: pAni = new Animal; break; } Virtual functions class Animal { public: Animal(); virtual ~Animal(); int getAge() const; virtual void speak() const; private: int m_age; }; base class •  pAni->speak(); class Dog : public Animal { public: Dog(); ~Dog(); string getName() const; void setName(string name); void speak() const; private: string m_name; }; derived class Polymorphism •  Late binding / dynamic binding –  The appropriate version is selected during runtime! •  Polymorphism –  pAni can take multiple forms. Animal *pAni; int x; cin >> x; switch (x) { case 1: pAni = new Dog; break; case 2: pAni = new Cat; break; default: pAni = new Animal; break; } Polymorphism: a realistic example Entity NonEnemyNPC fns: damage(), heal(), move() vars: energy, position Player Enemy fns: shoot() vars: equipments, items, exp fns: action() vars: itemsToDrop Zombie fns: action() fns: speak() vars: stuffToSay Robot fns: action() Player List of Enemy Pointers P Z R R R List of Entity Pointers Virtual functions class Animal { public: Animal(); virtual ~Animal(); int getAge() const; virtual void speak() const; private: int m_age; }; base class class Dog : public Animal { public: Dog(); ~Dog(); string getName() const; void setName(string name); void speak() const; private: string m_name; }; derived class •  Wait, what’s that virtual doing before the destructor of Animal? Note for Java programmers •  In Java, every function is virtual. Animal speaks? •  speak is a common feature among all (or many) animals. •  But it really means something only if we know what this animal is. •  Option 1: –  Get rid of speak() function in Animal, and implement it in all the derived classes. •  Then we can’t do pAni ­>speak()… •  Option 2: –  Make it a pure virtual function. Pure virtual functions •  You declare it in the base class, but don t define it, and add = 0 in the declaration. •  It is a dummy function. •  The derived class must implement all the pure virtual functions of its base class. class Animal { public: Animal(); virtual ~Animal(); int getAge() const; virtual void speak() const = 0; private: int m_age; }; Abstract base class •  If a class has at least one pure virtual function, it is called an abstract base class. Animal a1; // won t compile Animal *pAni = new Animal; // won t compile Animal *pAni = new Dog; // still works •  Animal is like a common interface without complete implementation. Or, one can think of it as a framework. Questions? Preview: Recursion •  Suppose I have the following function: A function calling int factorial(int n) itself! { if (n == 1) return 1; return n * factorial(n  ­ 1); } int y = factorial(4); Preview: Recursion int factorial(int n) n = 4 { if (n == 1) return 1; return n * factorial(n ­1); } factorial(4) int factorial(int n) n = 2 { if (n == 1) return 1; return n * factorial(n ­1); } factorial(2) int factorial(int n) n = 3 { if (n == 1) return 1; return n * factorial(n ­1); } factorial(3) int factorial(int n) n = 1 { if (n == 1) return 1; return n * factorial(n ­1); } Factorial(1) Preview: Recursion •  The technique of using a function that calls itself is called recursion. •  This is like the domino effect! factorial(1) factorial(2) factorial(3) factorial(4) •  It helps you reduce a big problem into a smaller one, thus makes the implementation a lot simpler. ...
View Full Document

This note was uploaded on 02/20/2012 for the course CS 32 taught by Professor Davidsmallberg during the Winter '08 term at UCLA.

Ask a homework question - tutors are online