CS 32 Lecture 7. Polymorphism

Jene Hojin Choi·2021년 7월 23일
0

C++

목록 보기
5/17
post-thumbnail

아래의 글은 제가 재학중인 UCLA의 CS 32: Data Structures의 렉쳐를 들으며 작성하는 글입니다.


📝 Polymorphism

Definition

Polymorphism: using a base pointer or a base reference to access a derived object

  • possible to design and implement extensible systems

In above code, SayHi function now treats variable p as if it referred to a Person variable.

In fact, SayHi has no idea that p refers to a Student!
Then SayHi will not be able to call specialized functions in derived function.



Chopping (object slicing)

If we remove the reference (& keyword in front of p), object slicing occurs.

C++ will basically chop off all the data/methods of the derived class and only send the base parts of variable s to the function.

We want to access the whole thing, but in this case, it creates a temporary variable that has no Student parts. We lose some information.



Example

Before polymorphism

In this exmaple, class Square and Circle are subclasses of class Shape.

We defined different PrintPrice() for each class Square and Circle, respectively PrintPriceSq() and PrintPriceCir().
This looks little redundant.



After polymorphism

We defined PrintPrice() to use both classes. C++ automagically knows which Shape (Square or Circle) it is.

We can also use it with base class, not with derived class.
In the following code, we just defined sh. Here we use base method.

Once again, PrintPrice() thinks every variable you pass in to it is just a Shape. Thus, functions specific to Circle or Square are totally invisible to it.
(because it is extension!)



✔️ Inheritance, Polymorphism

Inheritance: publicly derive one or more classes from a common base class.

All of the derived classes, by definition, inherit a common set of functions from our base class.

Each derived class may re-define any function originally defined in the base class. The derived class wil then have its own specialized version of the function.

Polymorphism: use a base pointer/ reference to access any variable that is of a type that is derived from the base class



When to use virtual?

  1. Use in a parent class when redefining a function in a child class.
  2. Use in a child class when redefining a function (for clarity. Not required)
  3. ALWAYS Use for the destructor in a parent class (and a child class for clarity)
  4. You can't have a virtual constructor tho!

What if we omit virtual keyword?

Q. What happens if we remove virtual keyword?

A. C++ will not be able to figure out the right version of the function to call, so it'll call the base version.



✔️ Pointers

In general, point a parent class pointer at a child class variable.
You may NEVER point a child class pointer at a parent class variable.

You can also use a pointer to an array. plotShape() will be virtual function.

In the following code, p will not be able to know if carey is Politician.

Question: What will be the result?

A. "tee hee hee"

Since there is virtual in the base class, C++ knows that laugh() is redefined in child classes, so it'll find a child class version in class HighPitchGeek.
Without it, it would use the base version.



✔️ Virtual Destructors

Even though p is a Prof pointer, it actually points to a MathProf variable.
C++ should call MathProf's destructor first and then Prof's destructor second.

What happens if destructors aren't virtual?

The program will crash! but only when we use polymorphism.
But to be safe, always use virtual destructors.

In the following code, we have polymorphism. MathProf's destructor will never get called and m_pTable will never get destructed! There will be a memory leak.



✔️ How polymorphism works

C++ basically prepares a box to store proper functions for derived class, which is called vtable.

However, do not make getX() and getY() virtual to make performance better. They are not overrided, so it's unnecessary.



✔️ Pure Virtual Functions

getArea() and getCircum() are dummy functions which return 0. Why would we want them?

They are never actually used, but they are base versions of specialized class.
However, we could remove the useless logic and define such abstract functions. These are called pure virtual functions.

// pure virtual functions
class Shape
{
public: 
   virtual float getArea() = 0;
   virtual float getCircum() = 0;
   
private:
    ...
}

Using pure virtual functions means the base version will never be called.
Thus, derived classes must redefine all pure virtual functions so they do something useful.
If not, complie error occurs.



✔️ Abstract Base Class

If there is at least one pure virtual function in a base class, it is called an "Abstract Base Class".

For example, getArea() is a pure virtual function, and Shape is an Abstract Base Class.

Which one is an ABC/ a regular class?

class Robot 
{
public: 
     virtual void talkToMe() = 0;
     virtual int getWeight() = 0;
     ...
}

class FriendlyRobot: public Robot
{
public:
     virtual void talkToMe(){
    	 cout << "I like geeks";
     }
....
};

class BigHappyRobot: public FriendlyRobot
{
public:
    virtual int getWeight() {
    	return 500;
    }
...  
}

Answer:

1. Robot: ABC
2. FriendlyRobot: ABC
: It inherits virtual int getWeight() from Robot, which is a pure virtual function.
3. BigHappyRobot: regular

With ABC

  • can't create a variable with an ABC
  • can use ABCs like regular base classes to implement polymorphism.

0개의 댓글