chapter 9 pointers, virtual functions and polymorphism
DESCRIPTION
Chapter 9 Pointers, Virtual Functions and Polymorphism. §9.1 Introduction §9.2 Pointers to Objects §9.3 Virtual Functions §9.4 Dynamic Casting. §9.1 Introduction. Polymorphism: “one name, multiple forms” Functions, data types Function binding Invocation statement function body - PowerPoint PPT PresentationTRANSCRIPT
Chapter 9 Pointers, Virtual Functions and Polymorphism
§9.1 Introduction
§9.2 Pointers to Objects
§9.3 Virtual Functions
§9.4 Dynamic Casting
§9.1 Introduction
Polymorphism: “one name, multiple forms” Functions, data types
Function binding Invocation statement function body
Compile time polymorphism Static (early) binding, static linking Function overloading Operator overloading
Run time polymorphism Dynamic (late) binding, dynamic linking Virtual function + pointer of base class
2
Techniques for Polymorphism
3
PolymorphismPolymorphism
Run timepolymorphism
Run timepolymorphism
Compile timepolymorphismCompile timepolymorphism
FunctionOverloading
FunctionOverloading
Operatoroverloading
Operatoroverloading
Virtual functionVirtual function
Example Situation
4
class HM {public: void show(){ cout<<"Human\n"; }};
class HM {public: void show(){ cout<<"Human\n"; }};
class CN: public HM {public: void show(){ cout<<“Chinese\n"; }};
class CN: public HM {public: void show(){ cout<<“Chinese\n"; }};
class CT: public CN{public: void show(){ cout<<“Cantonese\n"; }};
class CT: public CN{public: void show(){ cout<<“Cantonese\n"; }};
int fun(HM h){h.show();}fun(HM());fun(CN());fun(CT());
int fun(HM h){h.show();}fun(HM());fun(CN());fun(CT());
HumanHumanHuman
HumanHumanHuman
HumanChineseCantonese
HumanChineseCantonese
Dynamic bindingDynamic binding
Anonymous object!
Anonymous object!
§9.2 Pointers to Objects
Create objects at run timeclass item {};
item x;
item *it_ptr = &x;
Referring member functionsx.show();
it_ptr->show();
(*it_ptr).show();
Array of objectsitem * ptr = new item[10];
5
6
The “this” Pointer
A special built-in pointer that points to the current object Used to cope with hidden data fields
// Construct a circle object Circle::Circle(double radius) {
this->radius = radius; (*this).radius = radius;
}
// Construct a circle object Circle::Circle(double radius) {
this->radius = radius; (*this).radius = radius;
}
// Set a new radius void Circle::setRadius(double radius) {
this->radius = (radius >= 0) ? radius : 0; }
// Set a new radius void Circle::setRadius(double radius) {
this->radius = (radius >= 0) ? radius : 0; }
The “this” Pointer
Person &Person::greater(Person& x)
{
if (x.age>age)
return x;
else
return *this;
}
max = a.greater(b);
7
the invoking object!
the argument object!
Pointers to Derived Classes
Pointers of a base class type is compatible with pointers of a derived class
Statements for a base class is workable for derived classes
8
B *cptr;//pointer to class B type variable
B b;//base object
D d;//derived object
cptr = &b;//cptr points to object b
cptr->show();
cptr = &d; //cptr points to object d
cptr->show();
class B{
public:
int b;
void show()
{cout<<"b="<<b<<endl;}
};
class D : public B{
public:
int d;
void show(){
cout<<"b="<<b<<endl;
cout<<"d="<<d<<endl;
}
};
9
int main(){
B * bptr; //base pointer
B base; //base object
bptr = &base; bptr->b = 100;
cout<<"bptr …to base…\n“;
bptr->show();
D derived; //derived object
bptr = &derived; bptr->b=200;
cout<<"bptr …to derived…\n“;
bptr->show();
D *dptr;
dptr= &derived; dptr->d=300;
cout<<"dptr is derived type…\n“;
dptr->show();
cout<<"using ((D*)bptr)"<<endl;
((D*)bptr)->d=400;
((D*)bptr)->show();
return 0;
}
§9.3 Virtual Functions
10
The function declared with the keyword “virtual”
Overriding To redefine a virtual function in the derived class
class B { public: virtual string toString() { return "class B"; } };
class B { public: virtual string toString() { return "class B"; } };
class D: public B { string toString() { return "class D"; } };
class D: public B { string toString() { return "class D"; } };
class B {
public:
void display(){
cout<<“Display base";}
virtual void show(){
cout<<“\n show base“;}
};
class D: public B {
public :
void display(){
cout<<"Display derived";}
void show(){
cout<<“show derived";}
};
11
int main(){
B b;
D d;
B *bptr;
cout<<“bptr points to Base“;
bptr=&b;
bptr->display();
bptr->show();
cout<<“bptr points to Derived";
bptr = &d;
bptr->display();
bptr->show();
return 0;
}
Example of Virtual Functions
Realize dynamic binding Must be accessed by using object pointers/references
Must be defined in base class Should be redefined (overriding) in the derived
class If not, base version will be invoked
No virtual constructors Virtual destructors are allowed
Can be a friend of another class
12
Notes on Virtual Functions
Virtual Destructors
13
class B { public: ~B() { cout<<“Dest B\n”; } };
class B { public: ~B() { cout<<“Dest B\n”; } };
class D: public B { public: ~D() { cout<<“Dest D\n”; } };
class D: public B { public: ~D() { cout<<“Dest D\n”; } };
int main() { B *bp = new D(); …… delete bp; …… }
int main() { B *bp = new D(); …… delete bp; …… }
Dest BDest B Dest DDest BDest DDest B
virtual ~B(){virtual ~B(){
Pure Virtual Functions
A function without body does nothing, just a placeholder
Also called abstract function Classes has pure virtual function can’t be used to
create objects Compiler requires each derived class:
define the function, or continue to declare it as a abstract function
14
virtual void display() = 0;
Abstract Classes
15
Class is the abstraction of instances/objects A base class is more abstract/general than
derived classes Abstract class (抽象类 )
In logic: A class so abstract that it cannot have any specific instances It can only be used as base class
In syntax: A class with abstract functions (抽象函数 )
16
Abstract Function
I.e. Pure Virtual Function (纯虚函数 ) Can’t be implemented in abstract classes
For example
GeometricObject -color: string
-filled: bool
#GeometricObject()
#GeometricObject(color: string, filled: bool)
+getColor(): string
+setColor(color: string): void
+isFilled(): bool
+setFilled(filled: bool): void
+tostring(): string
+getArea(): double
+getPerimeter(): double
“ protected”
class GeometricObject{protected: GeometricObject(); GeometricObject(string color, bool filled);
public: string getColor(); void setColor(string color); bool isFilled(); void setFilled(bool filled); string toString(); virtual double getArea() = 0; virtual double getPerimeter() = 0;
private: string color; bool filled;};
class GeometricObject{protected: GeometricObject(); GeometricObject(string color, bool filled);
public: string getColor(); void setColor(string color); bool isFilled(); void setFilled(bool filled); string toString(); virtual double getArea() = 0; virtual double getPerimeter() = 0;
private: string color; bool filled;};
17
Abstract Class Example GeometricObject
-color: string
-filled: bool
#GeometricObject()
#GeometricObject(color: string, filled: bool)
+getColor(): string
+setColor(color: string): void
+isFilled(): bool
+setFilled(filled: bool): void
+tostring(): string
+getArea(): double
+getPerimeter(): double
Circle
-radius: double
+Circle()
+Circle(radius: double)
+Circle(radius: double, color: string, filled: bool)
+getRadius(): double
+setRadius(radius: double): void
+getDiameter(): double
Rectangle -width: double
-height: double
+Rectangle()
+Rectangle(width: double, height: double)
+Rectangle(width: double, height: double, color: string, filled: bool)
+getWidth(): double
+setWidth(width: double): void
+getHeight(): double
+setHeight(height: double): void
AbstractGeometricObject.hAbstractGeometricObject.h
RunRun
AbstractGeometricObject.cppAbstractGeometricObject.cpp
DerivedCircle2.hDerivedCircle2.h
DerivedCircle2.cppDerivedCircle2.cpp
Rectangle2.hRectangle2.h
Rectangle2.cppRectangle2.cpp
TestGeometricObject2 .cppTestGeometricObject2 .cpp
18
§9.4 Dynamic Casting
How to display radius, diameter, area, and perimeter if the object is a circle?
// A function for displaying a geometric objectvoid displayGeometricObject(GeometricObject &object){ cout << "The area is " << object.getArea() << endl; cout << "The perimeter is " << object.getPerimeter() << endl;}
// A function for displaying a geometric objectvoid displayGeometricObject(GeometricObject &object){ cout << "The area is " << object.getArea() << endl; cout << "The perimeter is " << object.getPerimeter() << endl;}
19
Dynamic Casting
The dynamic_cast operator checks if p points to a Circle object If yes, p1 is assigned the address of the object If no, p1 is assigned to NULL (the constant 0)
GeometricObject *p = &object;
Circle *p1 = dynamic_cast<Circle*>(p);
if (p1 != NULL)
{
cout << "The radius is " << p1->getRadius() << endl;
cout << "The diameter is " << p1->getDiameter() << endl;
}
RunRunDynamicCastingDemoDynamicCastingDemo
20
Upcasting and Downcasting
Upcasting Assigning a pointer of a derived class type to a pointer
of its base class type Done implicitly
Downcasting Assigning a pointer of a base class type to a pointer of
its derived class type Done explicitly using dynamic_cast
GeometricObject *p = new Circle(1);Circle *p1 = new Circle(2);p = p1;
GeometricObject *p = new Circle(1);Circle *p1 = new Circle(2);p = p1;
p1 = dynamic_cast<Circle*>(p);p1 = dynamic_cast<Circle*>(p);
21
The typeid Operator
To return the type information of a variable/object The information is stored in an object of class type_info
For example,
string x;cout << typeid(x).name() << endl;string x;cout << typeid(x).name() << endl;
Summary
Polymorphism Compile / Runtime polymorphism Object pointers this pointer Techniques to realize runtime polymorphism
Virtual function Invoked via pointer of base class
Abstract function
22
Review Questions
Q9.2 Q9.4 Q9.8
23