C++ Notes 2
C++ Notes 2
C++ Notes 2
Void Pointers
Constructor and inheritance
Polymorphism, Virtual Functions and Abstract Class
Virtual Function and Polymorphism
Pure Virtual Function and Abstract Class
Void Pointers
The void pointer, also known as the generic pointer, is a special type of pointer that can be pointed at
objects of any data type! A void pointer is declared like a normal pointer, using the void keyword as the
pointer’s type:
1
2 int nValue;
3 float fValue;
4
struct Something
5 {
6 int nValue;
7 float fValue;
8 };
9
10Something sValue;
11
void *pVoid;
12pVoid = &nValue; // valid
13pVoid = &fValue; // valid
14pVoid = &sValue; // valid
15
However, because the void pointer does not know what type of object it is pointing to, it can not be
dereferenced! Rather, the void pointer must first be explicitly cast to another pointer type before it is
dereferenced.
1int nValue = 5;
Similarly, it is not possible to do pointer arithmetic on a void pointer. Note that since void pointers can’t be
dereferenced, there is no such thing as a void reference.
The next obvious questions is: If a void pointer doesn’t know what it’s pointing to, how do we know what to
cast it to? Ultimately, that is up to you to keep track of.
1 #include <iostream>
2 enum Type{
11 break;
12 case STRING:
break;
14
}
15
}
16
int main(){ int nValue = 5;
17
float fValue = 7.5;
18
char *szValue = "Mollie";
19
Print(&nValue, INT);
20
Print(&fValue, FLOAT);
21 Print(szValue, STRING);
22 return 0;}
This program prints:
5
7.5
In these cases, you must explicitly specify which base class constructor should be called by the compiler. This is
done by specifying the arguments to the selected base class constructor in the definition of the derived class
constructor.
class Rectangle
{
private :
float length;
float width;
public:
Rectangle ()
{
length = 0;
width = 0;
}
float area()
{
return length * width ;
}
};
float volume()
{
return area() * height;
}
};
int main ()
{
Box bx;
Box cx(4,8,5);
cout << bx.volume() << endl;
cout << cx.volume() << endl;
return 0;
}
output :
0
160
A derived class can override a member function of its base class by defining a derived class member function
with the same name and parameter list.
It is often useful for a derived class to define its own version of a member function inherited from its base class.
This may be done to specialize the member function to the needs of the derived class. When this happens, the
base class member function is said to be overridden by the derived class.
class mother
{
public:
void display ()
{
cout << "mother: display function\n";
}
};
int main ()
{
daughter rita;
rita.display();
return 0;
}
output:
It is occasionally useful to be able to call the overridden version. This is done by using the scope resolution
operator to specify the class of the overridden member function being accessed.
{
public:
void display ()
{
cout << "daughter: display function\n\n";
mother::display();
}
};
output:
#include <iostream>
class Shape
{
protected:
double width, height;
public:
void set_data (double a, double b)
{
width = a; height = b; } };
int main ()
{
Shape *sPtr; //declare pointer variables of type Shape
Rectangle Rect; //create the object rect of type Rectangle
sPtr = &Rect; //make sPtr point to the object rect.
return 0;
}
Notice that even though rectPtr is poining to rect (object of type Rectangle), when the program executes, the
statement sets length and width of rectangle. If you tried to access area function of class Rectangle with sPtr it
will give you compiler error.
sPtr -> area()
is a compiler error !
It means base class pointer can not access the additional member function of its derived class. If we want
to do this we need to type cast the base class pointer.
cout << static_cast <Rectangle *> (sPtr) -> area() << endl;
The type cast informs the compiler that sPtr is actually pointing to a Rectangle object derived from the Shape
base class. In general, a pointer to a base class that actually points to a derived class object must first be
appropriately cast before the additional features of the derived class can be used.
#include <iostream>
using namespace std;
class Shape
{
protected:
double width, height;
public:
void set_data (double a, double b)
{
width = a;
height = b;
}
virtual double area()
{return 0;}
};
int main ()
{
Shape *sPtr;
Rectangle Rect;
sPtr = &Rect;
return 0;
}
Output :
15
A member of a class that can be redefined in its derived classes is known as a virtual member. In order to
declare a member of a class as virtual, we must precede its declaration with the keyword virtual. The member
function area() has been declared as virtual in the base class because it is later redefined in each
derived class. The advantage of having virtual function is that we are able to access area function of
derived class by pointer variable of base class.
A pure virtual function is sometimes called an abstract function, and a class with at least one pure virtual
function is called an abstract class. The C++ compiler will not allow you to instantiate an abstract class.
Abstract classes can only be subclassed: that is, you can only use them as base classes from which to derive
other classes.
A class derived from an abstract class inherits all functions in the base class, and will itself be an abstract class
unless it overrides all the abstract functions it inherits. The usefulness of abstract classes lies in the fact that they
define an interface that will then have to be supported by objects of all classes derived from it.
#include <iostream>
using namespace std;
class Shape
{
protected:
double width, height;
public:
void set_data (double a, double b)
{
width = a;
height = b;
}
virtual double area() = 0;
};
class Rectangle: public Shape
{
public:
double area () { return (width * height); } };
int main ()
{
Shape *sPtr;
Rectangle Rect;
sPtr = &Rect;
Triangle Tri;
sPtr = &Tri;