아래의 글은 제가 재학중인 UCLA의 CS 32: Data Structures의 렉쳐를 들으며 작성하는 글입니다.
Polymorphism: using a base pointer or a base reference to access a derived object
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.
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.
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.
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: 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
- Use in a parent class when redefining a function in a child class.
- Use in a child class when redefining a function (for clarity. Not required)
- ALWAYS Use for the destructor in a parent class (and a child class for clarity)
- You can't have a virtual constructor tho!
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.
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.
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.
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.
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.
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.
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.
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.
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 intgetWeight()
fromRobot
, which is a pure virtual function.
3. BigHappyRobot: regular
- can't create a variable with an ABC
- can use ABCs like regular base classes to implement polymorphism.