You are on page 1of 11

1

Dynamic Binding
Last updated Mar 1, 2004. Earlier, I explained how dynamic binding and polymorphism are related. However, I didn't explain how this relationship is implemented. Dynamic binding refers to the mechanism that resolves a virtual function call at runtime. This mechanism is activated when you call a virtual member function through a reference or a pointer to a polymorphic object. Imagine a class hierarchy in which a class called Shape serves as a base class for other classes (Triangle and Square): class Shape { public: void virtual Draw() {} //dummy implementation //.. }; class Square { public: void Draw(); //overriding Shape::Draw } class Triangle { public: void Draw(); //overriding Shape::Draw }

Draw() is a dummy function in Shape. It's declared virtual in the base class to enable derived classes to
override it and provide individual implementations. The beauty in polymorphism is that a pointer or a reference to Shape may actually point to an object of class Square or Triangle: void func(const Shape* s) { s->Draw() } int main() { Shape *p1= new Triangle; Shape *p2 = new Square; func(p1); func(p2); }

2
C++ distinguishes between a static type and a dynamic type of an object. The static type is determined at compile time. It's the type specified in the declaration. For example, the static type of both p1 and p2 is "Shape *". However, the dynamic types of these pointers are determined by the type of object to which they point: "Triangle *" and "Square *", respectively. When func() calls the member function Draw(), C++ resolves the dynamic type of s and ensures that the appropriate version of Draw() is invoked. Notice how powerful dynamic binding is: You can derive additional classes from Shape that override Draw() even after

func() is compiled. When func() invokes Draw(), C++ will still resolve the call according to the dynamic
type of s. As the example shows, dynamic binding isn't confined to the resolution of member function calls at runtime; rather, it applies to the binding of a dynamic type to a pointer or a reference that may differ from its static type. Such a pointer or reference is said to be polymorphic. Likewise, the object bound to such a pointer is a polymorphic object. Dynamic binding exacts a toll, though. Resolving the dynamic type of an object takes place at runtime and therefore incurs performance overhead. However, this penalty is negligible in most cases. Another advantage of dynamic binding is reuse. If you decide to introduce additional classes at a later stage, you only have to override Draw() instead of writing entire classes from scratch. Furthermore, existing code will still function correctly once you've added new classes. You only have to compile the new code and relink the program.

C++ virtual function is a member function of a class, whose functionality can be over-ridden in its derived classes. The whole function body can be replaced with a new set of implementation in the derived class. The concept of c++ virtual functions is different from C++ Function overloading.

C++ Virtual Function - Properties:


C++ virtual function is, A member function of a class Declared with virtual keyword Usually has a different functionality in the derived class A function call is resolved at run-time

The difference between a non-virtual c++ member function and a virtual member function is, the nonvirtual member functions are resolved at compile time. This mechanism is called static binding. Where as the c++ virtual member functions are resolved during run-time. This mechanism is known as dynamic binding.

C++ Virtual Function - Reasons:


The most prominent reason why a C++ virtual function will be used is to have a different functionality in the derived class. For example a Create function in a class Window may have to create a window with white background. But a class called CommandButton derived or inherited from Window, may have to use a gray background and write a caption on the center. The Create function for CommandButton now should have a functionality different from the one at the class called Window.

C++ Virtual function - Example:


This article assumes a base class named Window with a virtual member function named Create. The derived class name will be CommandButton, with our over ridden function Create.

3
class Window // Base class for C++ virtual function example { public: virtual void Create() // virtual function for C++ virtual function example { cout <<"Base class Window"<<ENDL; } }; class CommandButton : public Window { public: void Create() { cout<<"Derived class Command Button - Overridden C++ virtual function"<<ENDL; } }; void main() { Window *x, *y; x = new Window(); x->Create(); y = new CommandButton(); y->Create(); } The output of the above program will be, Base class Window Derived class Command Button If the function had not been declared virtual, then the base class function would have been called all the times. Because, the function address would have been statically bound during compile time. But now, as the function is declared virtual it is a candidate for run-time linking and the derived class function is being invoked.

C++ Virtual function - Call Mechanism:


Whenever a program has a C++ virtual function declared, a v-table is constructed for the class. The vtable consists of addresses to the virtual functions for classes and pointers to the functions from each of the objects of the derived class. Whenever there is a function call made to the c++ virtual function, the vtable is used to resolve to the function address. This is how the Dynamic binding happens during a virtual function call. Function overloading is the practice of declaring the same function with different signatures. The same function name will be used with different number of parameters and parameters of different type. But overloading of functions with different return types are not allowed. For example in this C++ Tutorial let us assume an AddAndDisplay function with different types of parameters. //C++ Tutorial - Sample code for function overloading void AddAndDisplay(int x, int y) { cout<<" C++ Tutorial - Integer result: "<<(x+y); } void AddAndDisplay(double x, double y)

4
{ } void AddAndDisplay(float x, float y) { cout<< " C++ Tutorial - float result: "<<(x+y); } Some times when these overloaded functions are called, they might cause ambiguity errors. This is because the compiler may not be able to decide what signature function should be called. If the data is type cast properly, then these errors will be resolved easily. Typically, function overloading is used wherever a different type of data is to be dealt with. For example this can be used for a function which converts farenheit to celsius and vice versa. One of the functions can deal with the integer data, other can deal float for precision etc., C++ Arrays are the data structures which can be used to store consecutive values of the same data types. C++ Arrays can be declared for all c++ data types viz., int, float, double, char, struct, char etc., All the values are stored in consecutive memory locations. The values can be accessed by using the position of the stored value. The Computer also stores C++ arrays in consecutive memory locations viz., 0,1,2 etc., This makes the C++ arrays' accessibility faster. Unlike other data structures like Linked list, queue etc., the access to the elements is very fast. C++ Arrays can be multi-dimensional. Most cases a maximum of 3 dimensions will suffice for programming. That too single dimension c++ arrays are the commonest. cout<< " C++ Tutorial - Double result: "<<(x+y);

Declaring C++ Arrays of int type:


The c++ arrays are declared with the data type name and the number of elements inside the square brackets. int var_name[50]; // C++ Array of type int with maximum size = 50. The above declaration means, the var_name is an array of integer type. The values inside this var_name array can be accessed by referring to the position of their elements like var_name[0], var_name[1] etc., All the C++ arrays are based on Zero index values. That means the position reference starts at 0 and counts till the n-1th position. So in the above array, 50 elements can be stored starting from 0 to 49. The maximum number of elements that can be stored or the maximum size of the c++ array is 50. The values can be stored and accessed as given in the following code snippet. var_name[0] = 0; var_name[1] = 1; var_name[2] = 30; printf("Position 0: %d, Position 1:%d, Position 2:%d\n", var_name[0], var_name[1], var_name[2]); Care should be taken while using or referring to the position of the element. The position reference should not exceed the maximum size specified in the declaration. If it exceeds, the program will not generate any compiler errors. But it will raise run time errors and exceptions. Declaration of a two dimensional array is also similar. A great example for a two dimensional c++ integer array will be matrix. int array_matrix[3][3]; //Matrix of 3 * 3 type using c++ array of int data type

Declaring C++ arrays of type float:


The declaration and use of c++ arrays in float type are the same as int. The declaration is written as follows.

5
float var_float[100]; //A c++ array of float type The above declaration means, the c++ float array contains 100 elements starting from position 0 till 99. The elements can be accessed as var_float[0], var_float[1], var_float[2] .. var_float[99]. var_float[0] = 10.05; var_float[1] = 11.04; var_float[99] = 87.65;

Declaring C++ arrays of type char:


This is one of the most widely used and problematic type of c++ array. When an array of char is declared, this char array can be used as a string with the maximum size as specified in the array declaration. When this c++ char array is declared with two dimensions, this can be thought as an array of strings. char var_char_array[50]; //Memory reserved for 50 characters. char var_char_init[] = "c++ char array string example"; // initialization without specifying the size Like the above the c++ char array can be declared with or without initializing values.

C++ Array Advantages:


Easier to declare and use. Can be used with all data types.

C++ Array Disadvantages:


Fixed size data. If the number of elements stored are less than the maximum size, then the rest of the memory space goes waste. If the number of elements to be stored are more than the maximum size, the array cannot accommodate those new values. A class in C++ is an encapsulation of data members and functions that manipulate the data. The class can also have some other important members which are architecturally important. This C++ Tutorial discusses the components of a C++ class. More C++ tutorials will follow.

C++ Tutorial - Class Data Members:

Very important point about the Data members in this C++ Tutorial! This title is not a keyword or a data type in C++. This is just to explain one of the logical classifications of the types of members that are available in C++. The data members can be of any legal data type, a class type, a struct type etc., They can also be declared as pointers and accessible normally as like other data members. The Example class given below in this C++ tutorial has two data members x and y of type integer.

C++ Tutorial - Function members in classes:


Functions declared inside a class can be any of the following four types. This C++ Tutorial explains each one of them as below.

Ordinary member functions :


These are ordinary functions defined with a return type and parameters. The return type can also be void. The special trait about member functions is they can access the private/protected data members of their class and manipulate them. No external functions can access the private/protected data members of a class. The sample below this C++ Tutorial uses an ordinary member function Add(), returning an integer value.

6 Constructors:
Constructors in C++ are special member functions of a class. They have the same name as the Class Name. There can be any number of overloaded constructors inside a class, provided they have a different set of parameters. There are some important qualities for a constructor to be noted. Constructors have the same name as the class. Constructors do not return any values Constructors are invoked first when a class is initialized. Any initializations for the class members, memory allocations are done at the constructor.

In the example class given below in this C++ tutorial has the constructor Example_Class(), with the same name as the class.

Destructors:
Destructors in C++ also have the same name, except for the fact that they are preceded by a '~' operator. The destructors are called when the object of a class goes out of scope. It is not necessary to declare a constructor or a destructor inside a class. If not declared, the compiler will automatically create a default one for each. If the constructor/destructor is declared as private, then the class cannot be instantiated. Check below for the sample class of the C++ tutorial for an example of destructor.

C++ Tutorial - Access Level:


The classes in C++ have 3 important access levels. They are Private, Public and Protected. The explanations are as follows.

Private:
The members are accessible only by the member functions or friend functions.

Protected:
These members are accessible by the member functions of the class and the classes which are derived from this class.

Public:
Accessible by any external member. Look at the sample class below.

C++ Tutorial - Example of a class:


class Example_class //Sample Class for the C++ Tutorial { private: int x; //Data member int y; // Data member public: Example_Class() //Constructor for the C++ tutorial { x = 0; y = 0; } ~Example_Class() //destructor for the C++ Tutorial {} int Add() { return x+y; } };

7
When a function is declared , the function is expanded at the calling block. The function is not treated as a separate unit like other normal functions. But a compiler is free to decide, if a function qualifies to be an inline function. If the inline function is found to have larger chunk of code, it will not be treated as an inline function, but as like other normal functions. Inline functions are treated like macro definitions by the C++ compiler. They are declared with the keyword inline as follows. //Declaration for C++ Tutorial inline sample: int add(int x,int y); //Definition for C++ Tutorial inline sample: inline int add(int x,int y) { return x+y; } In fact, the keyword inline is not necessary. If the function is defined with its body directly and the function has a smaller block of code, it will be automatically treated as inline by the compiler. As implied, inline functions are meant to be used if there is a need to repetitively execute a small block of code, which is smaller. When such functions are treated inline, it might result in a significant performance difference.

inline

Static data types can be accessed without instantiation of the class in C++. This is applicable for static
functions also. The differences between a static member function and non-static member functions are as follows.

A static member function can access only static member data, static member functions and data and functions outside the class. A non-static member function can access all of the above including the static data member. A static member function can be called, even when a class is not instantiated, a non-static member function can be called only after instantiating the class as an object. A static member function cannot be declared virtual, whereas a non-static member functions can be declared as virtual A static member function cannot have access to the 'this' pointer of the class.

The static member functions are not used very frequently in programs. But nevertheless, they become useful whenever we need to have functions which are accessible even when the class is not instantiated. The pointer is used as a pointer to the class object instance by the member function. The address of the class instance is passed as an implicit parameter to the member functions. The sample below, in this c++ Tutorial shows how to use it. It is a common knowledge that C++ keeps only one copy of each member function and the data members are allocated memory for all of their instances. This kind of various instances of data are maintained use this pointer. Look at the sample below, in this c++ Tutorial.

this

C++ Tutorial - important notes on this pointer:


this pointer stores the address of the class instance, to enable pointer access of the members to the member functions of the class. this pointer is not counted for calculating the size of the object. this pointers are not accessible for static member functions. this pointers are not modifiable.

Look at the following example to understand how to use the 'this' pointer explained in this C++ Tutorial. class this_pointer_example // class for explaining C++ tutorial { int data1; public:

8
//Function using this pointer for C++ Tutorial int getdata() { return this->data1; } //Function without using this pointer void setdata(int newval) { data1 = newval; } }; Thus, a member function can gain the access of data member by either using this pointer or not. Any data which is declared private inside a class is not accessible from outside the class. A function which is not a member or an external class can never access such private data. But there may be some cases, where a programmer will need need access to the private data from non-member functions and external classes. C++ offers some exceptions in such cases. A class can allow non-member functions and other classes to access its own private data, by making them as friends. This part of C++ tutorial essentially gives two important points. Once a non-member function is declared as a friend, it can access the private data of the class similarly when a class is declared as a friend, the friend class can have access to the private data of the class which made this a friend

Let's see a sample in this C++ tutorial for each of the above cases.

C++ Tutorial - Friend function sample:


#include <iostream.h> //Declaration of the function to be made as friend for the C++ Tutorial sample int AddToFriend(int x); class CPP_Tutorial { int private_data; friend int AddToFriend(int x); public: CPP_Tutorial() { private_data = 5; } }; int AddToFriend(int x) { CPP_Tutorial var1; return var1.private_data + x; } int main() { cout << "Added Result for this C++ tutorial: "<< AddToFriend(4)<<endl; } The output of the above C++ Tutorial sample will be Added Result for this C++ tutorial: 9

C++ tutorial - friend class:


Declaration of a friend class is also similar. Only thing is a class definition is slightly different.

9 C++ Tutorial - Friend function:


#include < iostream.h > class CPP_Tutorial { int private_data; friend class friendclass; public: CPP_Tutorial() { private_data = 5; } }; class friendclass { public: int subtractfrom(int x) { CPP_Tutorial var2; return var2.private_data - x; } }; int main() { friendclass var3; cout << "Added Result for this C++ tutorial: "<< var3.subtractfrom(2)<

The output of the above C++ Tutorial sample will be Subtracted Result for this C++ tutorial: 3 This is a good way out given by C++ to avoid restrictions on private variables. But this should be used with caution though. If all the functions and classes are declared as friends, then the concept of encapsulation and data security will go for a toss. That is why the concept of friend functions and classes should be used with proper judgment. Creating or deriving a new class using another class as a base is called inheritance in C++. The new class created is called a Derived class and the old class used as a base is called a Base class in C++ inheritance terminology. The derived class will inherit all the features of the base class in C++ inheritance. The derived class can also add its own features, data etc., It can also override some of the features (functions) of the base class, if the function is declared as virtual in base class.

C++ inheritance is very similar to a parent-child relationship. When a class is inherited all the functions and data member are inherited, although not all of them will be accessible by the member functions of the derived class. But there are some exceptions to it too.
Some of the exceptions to be noted in C++ inheritance are as follows. The constructor and destructor of a base class are not inherited the assignment operator is not inherited the friend functions and friend classes of the base class are also not inherited.

There are some points to be remembered about C++ inheritance. The protected and public variables or members of the base class are all accessible in the derived class. But a private member variable not accessible by a derived class. It is a well known fact that the private and protected members are not accessible outside the class. But a derived class is given access to protected members of the base class. Let us see a piece of sample code for C++ inheritance. The sample code considers a class named vehicle with two properties to it, namely color and the number of wheels. A vehicle is a generic term and it can later be extended to any moving vehicles like car, bike, bus etc.,

10
class vehicle //Sample base class for c++ inheritance tutorial { protected: char colorname[20]; int number_of_wheels; public: vehicle(); ~vehicle(); void start(); void stop(); void run(); }; class Car: public vehicle //Sample derived class for C++ inheritance tutorial { protected: char type_of_fuel; public: Car(); }; The derived class Car will have access to the protected members of the base class. It can also use the functions start, stop and run provided the functionalities remain the same. In case the derived class needs some different functionalities for the same functions start, stop and run, then the base class should implement the concept of virtual functions. C++ Variable argument functions are useful wherever we are not sure about the number of parameters to be passed. Not all the compilers have the ability to decipher variable arguments. But C++ compiler has the capability to decrypt a variable argument function and provide the parameter values inside the function. The first confusion that would arise when using a variable argument is to identify the type of the variable. The data type of the variable should be known prior to using it in a variable argument function. The algorithm/code inside the function should be able to manipulate the data properly. The argument values can be retrieved by using the va_arg, va_start and va_end macros. These macros assume that the function will be called with a fixed number of required parameters and variable number of optional parameters. The following sample program uses a function Add with variable arguments and returns the value of the added items. #include <stdio.h> #include <stdargs.h> int Add(int a,int b,...) { //This one handles 4 arguments in total. int l_ParamVal=0; int total=0; int i; //Declare a va_list macro and initialize it with va_start va_list l_Arg; va_start(l_Arg,a); //The required parameters can also be accessed directly l_ParamVal = a; printf("%d\n",l_ParamVal); if(l_ParamVal != -1) total = total +l_ParamVal; l_ParamVal = va_arg(l_Arg,int); printf("%d\n",l_ParamVal); if(l_ParamVal != -1) total = total +l_ParamVal;

11
l_ParamVal = va_arg(l_Arg,int); printf("%d\n",l_ParamVal); if(l_ParamVal != -1) total = total +l_ParamVal; l_ParamVal = va_arg(l_Arg,int); printf("%d\n",l_ParamVal); if(l_ParamVal != -1) total = total +l_ParamVal; va_end(l_Arg); return total; } void main() { printf("Total of C++ Variable Arguments: %d\n",Add(2,3,4)); }

You might also like