You are on page 1of 17

Virtual Functions

• A virtual function is a member function that is declared within a base


class and redefined by a derived class.
• virtual functions implement the "one interface, multiple methods"
philosophy that underlies polymorphism
• virtual functions important and capable of supporting run-time
polymorphism is how they behave when accessed via a pointer
Pointers to Derived Types
#include <iostream> int main()
using namespace std; {
class base { base *bp;
int i; derived d;
public: bp = &d; // base pointer points to derived
void set_i(int num) { i=num; } object
int get_i() { return i; } // access derived object using base pointer
}; bp->set_i(10);
cout << bp->get_i() << " ";
class derived: public base { /* The following won't work. You can't
int j; access element of
public: a derived class using a base class pointer.
void set_j(int num) { j=num; } bp->set_j(88); // error
cout << bp->get_j(); // error
int get_j() { return j; }
*/
};
return 0;
}
Solution to the problem
The pointer can be type casted and used to
access the derived class members.

• // access now allowed because of cast


((derived *)bp)->set_j(88);
cout << ((derived *)bp)->get_j();
Sample program
#include <iostream> int main()
using namespace std; {
class base { base *p, b;
public: derived1 d1;
virtual void vfunc() { derived2 d2;
cout << "This is base's vfunc().\n"; // point to base
} p = &b;
}; p->vfunc(); // access base's vfunc()
class derived1 : public base { // point to derived1
public: p = &d1;
void vfunc() { p->vfunc(); // access derived1's vfunc()
cout << "This is derived1's vfunc().\n"; // point to derived2
} p = &d2;
}; p->vfunc(); // access derived2's vfunc()
class derived2 : public base { return 0;
public: }
void vfunc() {
cout << "This is derived2's vfunc().\n";
}
};
• Name Type
p base class pointer
b object of base
d1 object of derived1
d2 object of derived2
• The key point here is that the kind of object to which p points
determines which version of vfunc() is executed.
• this determination is made at run time, and this process forms the
basis for run-time polymorphism.
Calling a Virtual Function Through a
Base Class Reference
#include <iostream> // Use a base class reference parameter.
using namespace std;
class base { void f(base &r) {
public: r.vfunc();
virtual void vfunc() { }
cout << "This is base's vfunc().\n";
} int main()
}; {
base b;
class derived1 : public base { derived1 d1;
public: derived2 d2;
void vfunc() { f(b); // pass a base object to f()
cout << "This is derived1's vfunc().\n"; f(d1); // pass a derived1 object to f()
} f(d2); // pass a derived2 object to f()
}; return 0;
}
class derived2 : public base {
public:
void vfunc() {
cout << "This is derived2's vfunc().\n";
}
};
The Virtual Attribute Is Inherited
/* derived2 inherits virtual function vfunc()
• from derived1. */
When a virtual function is inherited, its class derived2 : public derived1 {
virtual nature is also inherited public:
// vfunc() is still virtual
Eg: void vfunc() {
#include <iostream> cout << "This is derived2's vfunc().\n";
using namespace std; }
450 C + + : T h e C o m p l e t e R e f e r e n c e };
class base {
public: int main()
virtual void vfunc() { {
cout << "This is base's vfunc().\n"; base *p, b;
} derived1 d1;
}; derived2 d2;
class derived1 : public base { // point to base
public: p = &b;
void vfunc() { p->vfunc(); // access base's vfunc()
cout << "This is derived1's vfunc().\n"; // point to derived1
} p = &d1;
}; p->vfunc(); // access derived1's vfunc()
// point to derived2
p = &d2;
p->vfunc(); // access derived2's vfunc()
return 0;
}
Output
This is base's vfunc().
This is derived1's vfunc().
This is derived2's vfunc().
Virtual Functions Are Hierarchical
• A function declared as virtual by a base class need not be
overridden
• When a derived class fails to override a virtual function, then when
an object of that derived class accesses that function, the function
defined by the base class is used
#include <iostream> int main()
using namespace std; {
class base { base *p, b;
public: derived1 d1;
virtual void vfunc() { derived2 d2;
cout << "This is base's vfunc().\n"; // point to base
} p = &b;
}; p->vfunc(); // access base's vfunc()
// point to derived1
class derived1 : public base { p = &d1;
public: p->vfunc(); // access derived1's vfunc()
void vfunc() { // point to derived2
cout << "This is derived1's vfunc().\n"; p = &d2;
} p->vfunc(); // use base's vfunc()
}; return 0;
}
class derived2 : public base {
public:
// vfunc() not overridden by derived2,
base's is used
};
• Sample output
This is base's vfunc().
This is derived1's vfunc().
This is base's vfunc().

• inheritance is hierarchical => virtual functions are also hierarchical.


• when a derived class fails to override a virtual function,
• the first redefinition found in reverse order of derivation is used.
Pure Virtual Functions
• A pure virtual function is a virtual function that has no definition
within the base class.
• To declare a pure virtual function, use this general form:
virtual type func-name(parameter-list) = 0;

• When a virtual function is made pure, any derived class must


provide its own definition.
• If the derived class fails to override the pure virtual function, a
compile-time error will result.
#include <iostream> class octtype : public number {
using namespace std; public:
class number { void show() {
protected: cout << oct << val << "\n";
int val; }
public: };
void setval(int i) { val = i; }
// show() is a pure virtual function int main()
virtual void show() = 0; {
}; dectype d;
hextype h;
class hextype : public number { octtype o;
public: d.setval(20);
void show() { d.show(); // displays 20 - decimal
cout << hex << val << "\n"; h.setval(20);
} h.show(); // displays 14 - hexadecimal
}; o.setval(20);
o.show(); // displays 24 - octal
class dectype : public number { return 0;
public: }
void show() {
cout << val << "\n";
}
};
Abstract Classes
• A class that contains at least one pure
virtual function is said to be abstract.
• no objects of an abstract class may be
created.
• pointers and references to an abstract
class can be created.
• This allows abstract classes to support
run-time polymorphism.
Using Virtual Functions
• Uses the principle of "one interface,
multiple methods."
• a general class of actions can be defined,
the interface to which is constant, with
each derivation defining its own specific
operations.
// Virtual function practical example. // Fahrenheit to Celsius
#include <iostream> class f_to_c : public convert {
using namespace std; public:
f_to_c(double i) : convert(i) { }
class convert { void compute() {
protected: val2 = (val1-32) / 1.8;
double val1; // initial value }
double val2; // converted value };
public:
convert(double i) { int main()
val1 = i; {
} convert *p; // pointer to base class
double getconv() { return val2; } l_to_g lgob(4);
double getinit() { return val1; } f_to_c fcob(70);
virtual void compute() = 0; // use virtual function mechanism to convert
}; p = &lgob;
cout << p->getinit() << " liters is ";
// Liters to gallons. p->compute();
class l_to_g : public convert { cout << p->getconv() << " gallons\n"; // l_to_g
public: p = &fcob;
l_to_g(double i) : convert(i) { } cout << p->getinit() << " in Fahrenheit is ";
void compute() { p->compute();
val2 = val1 / 3.7854; cout << p->getconv() << " Celsius\n"; // f_to_c
} return 0;
}; }

You might also like