virtual functions junaed sattar november 10, 2008 lecture 10

Post on 23-Dec-2015

213 Views

Category:

Documents

0 Downloads

Preview:

Click to see full reader

TRANSCRIPT

Virtual Functions

Junaed Sattar

November 10, 2008Lecture 10

Constructor/Destructor Order

Destructors, constructors, and assignment operators are not inherited they may be called automatically were

necessary Constructors are called from the “bottom

up” Destructors are called from the “top

down”

Example

class Base {public:Base() { cout << "calling base constructor." << endl; }~Base() { cout << "calling base destructor." << endl; }};

class Derived1: public Base{public:Derived1() { cout << "calling derived1 constructor." << endl; }~Derived1() { cout << "calling derived1 destructor." << endl; }};

class Derived2 :public Derived1{public:Derived2() { cout << "calling derived2 constructor." << endl; }~Derived2() { cout << "calling derived2 destructor." << endl; }};

int main(){ Derived2 d;

}

Output

calling base constructor.

calling derived1 constructor.

calling derived2 constructor.

calling derived2 destructor.

calling derived1 destructor.

calling base destructor.

Virtual Functions

C++ matches a function call with the correct function definition at compile time known as static binding

the compiler can match a function call with the correct function definition at run time known as dynamic binding. declare a function with the keyword virtual if

you want the compiler to use dynamic binding for that specific function.

Virtual Methods

Therefore, a virtual function is a member function you

may redefine for other derived classes, can ensure that the compiler will call the

redefined virtual function for an object of the corresponding derived class,

even if you call that function with a pointer or reference to a base class of the object.

A class that declares or inherits a virtual function is called a polymorphic class.

Declaring virtual

prefix declaration with the virtual keyword

redefine a virtual member function in any derived class

this is called overriding understand the contrast with overloading

More on definition

overridden function must have same name and same parameter list no need to use the virtual keyword again return type can be different

if the parameter lists are different, they are considered different in this case, it is not overridden, but hidden hidden methods cannot be called

Exampleclass A {

public:virtual void f() { cout << "Class A" << endl; }};

class B: public A {

public:void f(int) { cout << "Class B" << endl; }};

class C: public B {

public:void f() { cout << "Class C" << endl; }};

Output

int main() {B b; C c;A* pa1 = &b;A* pa2 = &c;// b.f();pa1->f();pa2->f();}

Outputs:

Class A

Class C

Synopsis

b::f() is not allowed it hides A::f() (a virtual function) not overloading (why?)

method overloading must happen within the same class, not in inheritance hierarchies

c::f() is allowed virtual, overrides A::f()

So, why?

a hierarchy of geometric shape classes draws circles,

ellipses, rectangles etc

just use method draw throughout the hierarchy

Line

Rectangle Circle

Square Ellipse

draw()

draw()

draw()

draw()

draw()

More why

to enforce a software design developers must define their own

implementation e.g. ImagingDevice objects (webcam,

firewire, disk images, movies ..) must acquire frames in their own way should have uniform interface (hiding

implementation details) use pure virtual methods

“Pure”ly Virtual a virtual function declared with no

definition base class contains no implementation at all

class containing a pure virtual function is an abstract class similar to Java interfaces cannot instantiate from abstract classes

enforces a design through inheritance hierarchy inherited classes must define

implementation

Example

class A {public:virtual void f() = 0; // pure virtual};

class B: public A {

public:void f() { cout << "Class B" << endl; }};

class C: public B {

public:void f() { cout << "Class C" << endl; }};

Output

int main() {B b; C c;A* pa1 = &b;A* pa2 = &c;pa1->f();pa2->f();}

Outputs:

Class B

Class C

Another example

class ImagingDevice {protected:

unsigned char *buffer;int width, height;...

public:ImagingDevice();virtual ~ImagingDevice(); // virtual destructor...virtual bool InitializeDevice() = 0;virtual bool GetImage()=0;virtual bool UninitializeDevice() = 0;virtual void SaveImage()=0;...

};

Continuing

class USBDevice: public ImagingDevice {...

public:USBDevice();virtual ~USBDevice();

...};

bool USBDevice::InitializeDevice(){ ... }bool USBDevice::UninitializeDevice(){ ... }bool USBDevice::GetImage(){ ... }void USBDevice::SaveImage(){ ... }

Why virtual destructor?

for properly cleaning up dynamically allocated memory

class Base{public:

Base(){}...

};

class Derived: public Base {int *memory;

public:Derived(){ memory = new int[1000]; }~Derived(){ delete [] memory; }

}

Virtual Destructor

int foo() {Base *b = new Derived();...delete b; // will not call destructor of d, as it

// should, (why?)}

Diagnosis

If not declared virtual, compiler uses type of pointer to decide which method to call in this case, b is of type Base, so the Base

destructor will get called memory leak from d (how?)

solution: always declare destructors virtual, even if no other virtual functions

Next

Generic programming with templates The Standard Template Library

top related