Introduction To C++ Part 3
Introduction To C++ Part 3
Encapsulation
OOP
Inheritance
Abstraction
Using subclasses
A function that takes a superclass
argument can also be called with void PrintArea(Rectangle &rT) {
a subclass as the argument. cout << rT.Area() << endl ;
}
Super sP ;
“C++ is an insult to the human brain” Func(sP) ; // Prints 1
– Niklaus Wirth (designer of Pascal) Sub sB ;
Func(sB) ; // Hey!! Prints 1!!
void FuncRef(Super &sP) {
sP.PrintNum() ;
Type casting }
When methods are overridden and called there are two points where
the proper version of the method can be identified: either at compile
time or at runtime.
class SuperVirtual
{
public:
Virtual methods virtual void PrintNum()
{
When a method is labeled as virtual and cout << 1 << endl ;
}
overridden the compiler will generate } ;
code that will check the type of an object
class SubVirtual : public SuperVirtual
at runtime when the method is called. {
public:
// Override
The type check will then result in the virtual void PrintNum()
expected version of the method being {
cout << 2 << endl ;
called. }
} ;
Late binding allows for code libraries to be updated for new functionality. As methods are identified
at runtime the executable does not need to be updated.
This is done all the time! Your C++ code may be, for example, a plugin to an existing simulation
code.
Greater flexibility when dealing with multiple subclasses of a superclass.
Most of the time this is the behavior you are looking for when building class hierarchies.
Shape
#include "rectangle.h"
An interface class in C++ is called a pure virtual class.
class Log {
It contains virtual methods only with a special syntax. virtual void LogInfo()=0 ;
Instead of {} the function is set to 0. };
Any subclass needs to implement the methods!
Modified square.h shown. class Square : public Rectangle, Log
{
What happens when this is compiled? public:
(…error…) Square(float length);
include/square.h:10:7: note: because the following virtual virtual ~Square();
functions are pure within 'Square': // virtual void LogInfo() {}
class Square : public Rectangle, Log
^ protected:
include/square.h:7:18: note: virtual void Log::LogInfo()
virtual void LogInfo()=0 ; private:
};
Once the LogInfo() is uncommented it will compile.
#endif // SQUARE_H
C++ offers another fix for the diamond problem, Virtual inheritance. See: https://en.wikipedia.org/wiki/Virtual_inheritance
Putting it all together
Shape
#endif // SHAPE_H
Give it a try
Add inheritance from Shape If you just want to see a
to the Rectangle class solution, open the project
Add a Circle class, inheriting “Shapes with Circle solved”
from wherever you like.
Implement Area() for the
Circle
A Potential Solution
Shape
protected:
private:
};
#endif // CIRCLE_H
#include "circle.h"
Circle::Circle()
{
//ctor
}
circle.cpp
Circle::~Circle()
Questions? {
//dtor
}
float Circle::Area()
{
// Quiz: what happens if this line is
// uncommented and then compiled:
//PI=3.14159 ;
return m_radius * m_radius * PI ;
}
Quiz time!
void PrintArea(Shape &shape) {
cout << "Area: " << shape.Area() << endl ;
}
int main()
What happens behind {
the scenes when the Square sQ(4) ;
Circle circ(3.5) ;
function PrintArea is Rectangle rT(21,2) ;
called?
// Print everything
How about if PrintArea’s PrintArea(sQ) ;
argument was instead: PrintArea(rT) ;
PrintArea(circ) ;
return 0;
void PrintArea(Shape shape) }
Quick mention…