You are on page 1of 52

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 non-virtual 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. 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 v-table 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 v-table is used to resolve to the function address. This is how the Dynamic binding happens during a virtual function call.

C++ Virtual Functions What are Virtual Functions?


Virtual, as the name implies, is something that exists in effect but not in reality. The concept of virtual function is the same as a function, but it does not really exist although it appears in needed places in a program. The object-oriented programming language C++ implements the concept of virtual function as a simple member function, like all member functions of the class. Sponsored Links The functionality of virtual functions can be over-ridden in its derived classes. The programmer must pay attention not to confuse this concept with function overloading. Function overloading is a different concept and will be explained in later sections of this tutorial. Virtual function is a mechanism to implement the concept of polymorphism (the ability to give different meanings to one function).

Need for Virtual Function:


The vital reason for having a virtual function is to implement a different functionality in the derived class.

For example: a Make function in a class Vehicle may have to make a Vehicle with red color. A class called FourWheeler, derived or inherited from Vehicle, may have to use a blue background and 4 tires as wheels. For this scenario, the Make function for FourWheeler should now have a different functionality from the one at the class called Vehicle. This concept is called Virtual Function.

Properties of Virtual Functions:


Dynamic Binding Property:

Virtual Functions are resolved during run-time or dynamic binding. Virtual functions are also simple member functions. The main difference between a non-virtual C++ member function and a virtual member function is in the way they are both resolved. A non-virtual C++ member function is resolved during compile time or static binding. Virtual Functions are resolved during run-time or dynamic binding

Virtual functions are member functions of a class. Virtual functions are declared with the keyword virtual, detailed in an example below. Virtual function takes a different functionality in the derived class.

Declaration of Virtual Function:


Virtual functions are member functions declared with the keyword virtual. For example, the general syntax to declare a Virtual Function uses:

class classname //This denotes the base class of C++ virtual function { public: virtual void memberfunctionname() //This denotes the C++ virtual function { ............. ............ } };

Referring back to the Vehicle example, the declaration of Virtual function would take the shape below:

class Vehicle //This denotes the base class of C++ virtual function { public: virtual void Make() //This denotes the C++ virtual function {

cout <<"Member function of Base Class Vehicle Accessed"<<endl; } }; After the virtual function is declared, the derived class is defined. In this derived class, the new definition of the virtual function takes place. When the class FourWheeler is derived or inherited from Vehicle and defined by the virtual function in the class FourWheeler, it is written as:

class Vehicle //This denotes the base class of C++ virtual function { public: virtual void Make() //This denotes the C++ virtual function { cout <<"Member function of Base Class Vehicle Accessed"<<endl; } }; class FourWheeler : public Vehicle { public: void Make() { cout<<"Virtual Member function of Derived class FourWheeler Accessed"<<endl; } }; void main() { Vehicle *a, *b; a = new Vehicle(); a->Make(); b = new FourWheeler(); b->Make(); }

In the above example, it is evidenced that after declaring the member functions Make() as virtual inside the base class Vehicle, class FourWheeler is derived from the base class Vehicle. In this derived class, the new implementation for virtual function Make() is placed. The programmer might be surprised to see the function call differs and the output is then printed as above. If the member function has not been declared as virtual, the base class member function is always called because linking takes place during compile time and is therefore static.

Sponsored Links In this example, the member function is declared virtual and the address is bounded only during run time, making it dynamic binding and thus the derived class member function is called. To achieve the concept of dynamic binding in C++, the compiler creates a v-table each time a virtual function is declared. This v-table contains classes and pointers to the functions from each of the objects of the derived class. This is used by the compiler whenever a virtual function is needed.

C++ Pure Virtual Function and Virtual Base Class


In this C++ tutorial, you will learn about pure virtual function, declaration of pure virtual function and virtual base class, virtual base class and how to implement a virtual base class, explained with examples. Sponsored Links

What is Pure Virtual Function:


Pure Virtual Function is a Virtual function with no body.

Declaration of Pure Virtual Function:


Since pure virtual function has no body, the programmer must add the notation =0 for declaration of the pure virtual function in the base class. General Syntax of Pure Virtual Function takes the form:

class classname //This denotes the base class of C++ virtual function { public: virtual void virtualfunctioname() = 0 //This denotes the pure virtual function in C++ }; The other concept of pure virtual function remains the same as described in the previous section of virtual function. To understand the declaration and usage of Pure Virtual Function, refer to this example:

class Exforsys {

public: virtual void example()=0; //Denotes pure virtual Function Definition }; class Exf1:public Exforsys { public: void example() { cout<<"Welcome"; } }; class Exf2:public Exforsys { public: void example() { cout<<"To Training"; } }; void main() { Exforsys* arra[2]; Exf1 e1; Exf2 e2; arra[0]=&e1; arra[1]=&e2; arra[0]->example(); arra[1]->example(); } Since the above example has no body, the pure virtual function example() is declared with notation =0 in the base class Exforsys. The two derived class named Exf1 and Exf2 are derived from the base class Exforsys. The pure virtual function example() takes up new definition. In the main function, a list of pointers is defined to the base class. Two objects named e1 and e2 are defined for derived classes Exf1 and Exf2. The address of the objects e1 and e2 are stored in the array pointers which are then used for accessing the pure virtual function example() belonging to both the derived class EXf1 and EXf2 and thus, the output is as in the above example. The programmer must clearly understand the concept of pure virtual functions having no body in the base class and the notation =0 is independent of value assignment. The notation =0 simply indicates the Virtual function is a pure virtual function as it has no body. Some programmers might want to remove this pure virtual function from the base class as it has no body but this would result in an error. Without the declaration of the pure virtual function in the base class, accessing statements of the pure virtual function such as, arra[0]->example() and arra[1]->example() would result in an

error. The pointers should point to the base class Exforsys. Special care must be taken not to remove the statement of declaration of the pure virtual function in the base class.

Virtual Base Class

In the above example, there are two derived classes Exf1 and Exf2 from the base class Exforsys. As shown in the above diagram, the Training class is derived from both of the derived classes Exf1 and Exf2. In this scenario, if a user has a member function in the class Training where the user wants to access the data or member functions of the class Exforsys it would result in error if it is performed like this:

class Exforsys { protected: int x; }; class Exf1:public Exforsys { }; class Exf2:public Exforsys { }; class Training:public Exf1,public Exf2 { public: int example() { return x; } }; The above program results in a compile time error as the member function example() of class Training tries to access member data x of class Exforsys. This results in an error because the derived classes Exf1 and Exf2 (derived from base class Exforsys) create copies of Exforsys called subobjects.

This means that each of the subobjects have Exforsys member data and member functions and each have one copy of member data x. When the member function of the class Training tries to access member data x, confusion arises as to which of the two copies it must access since it derived from both derived classes, resulting in a compile time error. When this occurs, Virtual base class is used. Both of the derived classes Exf1 and Exf2 are created as virtual base classes, meaning they should share a common subobject in their base class. For Example:

class Exforsys { protected: int x; ; class Exf1:virtual public Exforsys { }; class Exf2:virtual public Exforsys { }; class Training:public Exf1,public Exf2 { public: int example() { return x; } }; Sponsored Links In the above example, both Exf1 and Exf2 are created as Virtual base classes by using the keyword virtual. This enables them to share a common subobject of their base class Exforsys. This results in only one copy that the member function example() of Class Training can access the member data x.

Introduction

In this article i am writing about pointers, one of the exciting features of C and C++ language. One must say that pointers are the source of much confusion, as well as the cause of many programming errors. Internally almost every C program makes use of pointers. Prior to understanding the importance of pointers, it is necessary to understand about the basic concept of memory in computers.

Memory and Addresses


In computers memory, every byte has an address. Addresses are basically numbers that starts at 0 and end at the highest address, which will vary according to the amount of memory available in the computer as shown in Figure 1. From this figure, it is clear that storage locations are the numbers, just as they are for post offices. For a 640kb of memory, we have addresses from 0 to 65535. Note that the address of a variable is not the same as its contents. The address is the memory location, which is used to store the data. One or more storage location is capable of storing a piece of data. But the address of a data item is the address of its first storage location. Storage location is primarily used when we want to extract data or when we want to store data. The address of a data item is called a pointer to that data item.

Figure 1

The

Concept

of

Pointers

Every variable and every function in a C program starts at a particular address. The address of a data item is called a pointer and a variable that contains the address of another variable or a function is called a pointer variable. Like any basic data type variable, a pointer variable must be declared prior to its use. Each pointer variable can point only to one specific basic data type, such as int, float, char, or user-defined data type, such as struct and union.

The

Address

Operator

(&)

To obtain the address of a variable, C provides a unary operator & (ampersand). This operator is known as the address operator. When the address operator (&) precedes a variable name, it yields address of that variable. Note that this address operator can precede only a variable name or array element, but never a constant, an expression, the unsubscripted name of an array.

Now let us start from the beginning. Firstly we will see what happens when we create a variable. For example, if we declare an integer variable x as:

int x = 100;

/* int variable */

then (i) (ii) (iii)

the reserves associate stores

C memory a the space

compiler to contain x 100

performs an with at integer this this

three value, memory memory say

actions: 65524 location location

name value

Figure-.2 shows these actions.

This figure shows that the variable x has selected memory location 65524 in order to store the value 100. You can obtain this address easily by using the address operator, that is &x gives the address of variable x.

Following program-1.c illustrates the use of & operator.

/* #include main() {

Program

1.c

*/

int printf("\nAddress } : %u

x contains a value

= : %d", &x,

100; x);

When Address

we :

execute 65524

this

program, contains

we a

get

following value :

output. 100

This output displays the address in decimal notation. By default in C, the address is displayed in decimal notation. However by default in a C++ we obtain the address in hexadecimal notation. Now look at the printf statement:

printf("\nAddress : %u contains a value : %d", &x, x);

In this statement, we have used format specifier %u and %d. As we know the %d specifier is used for integer number. But what about format specifier %u ? Actually we all know that a memory location can not

be a negative number, and a non-negative number is always an unsigned number. For unsigned numbers, C provides %u specifier for displaying unsigned decimal number. However in C, you can also display the address of a variable in hexadecimal notation by replacing %u by %x. Thus the following printf() statement

printf("\nAddress : %x contains a value : %d", &x, x);

displays Address : fff4

the contains

following a value :

output: 100

Also remember that the address of any user-defined data type variable will also be an unsigned integer number.

Pointer

Variables

A variable that contains the address of another variable is called a pointer variable. A pointer variable is a variable that must be declared like any ordinary variable. The pointer is declared using an asterisk (*) operator. The general form of a pointer declaration is:

datatype *pointervariablename;

Here datatype could be any basic data type like int, float, char or user-defined data types, such as struct or union. The pointervariablename could be any valid C variable name. The pointer-variable-name holds the address of any variable of the specified datatype. However, you can also declare a pointer variable as:

datatype* pointer-variable-name;

For example, in the following declaration

int ptr;

/* pointer to int variable */

ptr is a pointer variable which stores an address of the location where the integer variable is stored. Similarly a pointer to a float variable is declared as:

float *j;

A pointer variable does not point to anything until it is explicitly assigned the address of an ordinary variable. When a variable is declared as a pointer, it is not automatically initialized to any value, we have to explicitly assign the address of another variable to it. For example, in the following statements:

int a, *b; b = &a;

the address of integer variable a is assigned to a pointer variable b. However a pointer variable can also be initialized in its declaration. Above two statements can also be rewritten as:

int a, *b = &a;

This statement declares a as an ordinary variable of type int, declares b as a pointer to int, and initializes b to the address of a.

The Indirection Operator (*)

The operator *, when applied to an address (pointer) fetches the value at that address. The operator * is referred to as the indirection or dereferencing operator. When an indirection operator is applied on a pointer variable it yields the value contained in the memory location pointed to by the pointer variables.

For example, if b is a pointer to an integer then the type of *b would an integer value. For example, consider the following statements:

int a = 10, n, *b; b = &a; n = b; /* retrieve value that int pointer points to */

Here the last two statements

b = &a; n = *b;

are equivalent to the single statement

n = *(&a); or n = a;

From this result, it is clear that the address operator (&) is the inverse of the indirection operator. Following program illustrates this concept.

/* Program - 2.c */ #include main() { int a=10, *b; b = &a;

printf("\nAddress : %u contains a value : %d", &a, a); printf("\nAddress : %u contains a value : %d", &a, *(&a)); printf("\nAddress : %u contains a value : %d", b, a); printf("\nAddress : %u contains a value : %d", b, *b); }

When you run this program, you get the following output.

Address : 65524 contains a value : 10 Address : 65524 contains a value : 10 Address : 65524 contains a value : 10 Address : 65524 contains a value : 10

One main point to remember is that pointers and integers are not interchangeable. Thus the following statements are completely invalid:

int a=10, *b; b = 65524; /* Illegal */

An exception to this rule is the constant 0 that can be assigned to a pointer at any time because a pointer value 0 is defined as NULL value in the standard header file . Thus the following statement is completely valid:

b = 0;

/* Legal */

The void Pointers


If a pointer is defined to be of a specific data type then it can not hold the address of any other type of variable. It means that we can not store the address of a float variable in an integer pointer variable as:

int *b; float p = 40.75; b = &p /* Illegal */

Likewise a pointer of one data type can not be assigned to a pointer of another data type until it is explicitly performed typecasting as:

int a=10, *b; float p = 40.75, *x; b=&a; x=&p; x = b; /* Illegal */ /* Legal */

x = (float *)b;

Here the last statement performs the conversion of an int pointer into a float pointer. The basic principal behind this conversion of one pointer type to another is that the conversion of a pointer b into a pointer to x and back is possible only if x requires less or equally strict storage alignment when compared to b; otherwise some addressing exception may occur when the resulting pointer is dereferenced. This type of problem is overcome by using generic pointers. These generic pointers are called as void pointers.

The syntax of declaring a void pointer is as:

void *vptr;

Here void is a keyword and vptr is any valid identifier name. The void pointer does not have any type associated with it and therefore it can contain the address of any type of variable. Following code segment illustrates this:

void *vptr; int a=10, *b; float p = 40.75, *x; b=&a; x=&p; vptr=&a; /* Legal */

vptr=&p; vptr = b; vptr = x;

/* Legal */ /* Legal */ /* Legal */

Thus any pointer can be converted to a void pointer and back without loss of information. But one should remember very carefully that pointer to void can not be directly dereferenced like other normal pointer variable by using the indirection operator (*). Following statements illustrates this.

void *vptr; int a=10, *b; vptr = b; a = *vptr+10; /* Legal */ /* Illegal */

A void pointer can only be dereferenced only when it is suitably typecast to the required data type, as illustrated below:

a = *((int *)vptr)+10;

/* Legal */

Here a void pointer is typecast by preceding its name with an int data type followed by an asterisk, both of which are enclosed within a pair of parentheses.

Arithmetical View of Pointers

As stated earlier pointers are unsigned integer variables by which we can add integer values as well as subtract them from a pointer. But the main difference between a normal integer and an integer pointer is that pointer arithmetic adds and subtracts the size of the data type to which the pointer points.

For example, when we add 1 to any integer pointer, it is incremented by the size of an integer variable. We know that each integer data occupies two bytes in memory therefore if we add 1 to an integer pointer then actually we are adding 2 to it. For example, let we have an integer pointer variable iptr containing an address 62400 then after execution of the following statement:

iptr = iptr+4;

the value of iptr becomes 62408. Similarly when we subtract any integer number say 2, it is decremented by 4, that is

iptr = iptr-2;

results in 62404. A float pointer variable value increases or decreases by 4 when it is incremented or decremented. In the same fashion if we say add 1 to any float pointer, it is incremented by 4, that is the size of a float data type. Similarly when we increment/decrement a character pointer variable, its value is increment/decrement by 1. It means that in pointer arithmetic, all pointers increase and decrease by the length of the data type they point to. While using pointer arithmetic, one should be very careful. Pointer arithmetic is restricted to only a few basic operations. These operations are summarized as:

1. 2. 3. 4.

Adding a constant integer value to a pointer Subtracting a constant integer value from a pointer Subtracting the value of one pointer from another of the same data type Comparing the values two pointers of the same data type

Pointers and Arrays

One should be surprised to know that all arrays make use of pointers internally. In general, any operation that can be achieved by array subscripting can also be done with pointers. Now let us see how this is possible. We know that array elements are always stored in contiguous memory locations irrespective of the size of the array. And a pointer when incremented always point to an immediately location of its type. Since all the array elements are stored in contiguous memory locations, therefore if we store the base address of an array in a pointer variable then we can easily access other array elements. For example, let ptr is a pointer variable and it contains the base address of array arr[] as:

int *ptr = arr; or int *ptr = &arr[0];

/* address of array arr */

on incrementing the value of ptr as:

ptr++;

it will point to the second element of the array. And once we have an address, we can easily access the value stored at that address.

Following program shows this concept.

/* Program - 3.c */ #include

main() { int arr[5] = {10, 20, 30, 40, 50}; int i, *ptr; ptr = arr;

for(i=0; i<5; i++) { printf("\nAddress : %u contains a value : %d", ptr, *ptr); ptr++; } }

The output of this program is as:

Address : 64820 contains a value : 10 Address : 64822 contains a value : 20 Address : 64824 contains a value : 30 Address : 64826 contains a value : 40 Address : 64828 contains a value : 50

In this program, an integer pointer ptr is explicitly declared and assigned the starting address (base address) of the array and within loop, the value of ptr is incremented in each iteration. Since the name of array is a synonym for the location of the initial element, therefore the address of first element can be expressed as either arr or (arr+0) or &arr[0]. The address of the second element can be written as either arr+1 or &arr[1]. In general the address of (i+1)th array element can be expressed as either (arr+i) or &arr[i]. Now if we apply indirection operator then we can easily obtain the contents stored on that particular address. Following table summarizes this.

*(arr+0) *(arr+1) *(arr+2) *(arr+3) . *(arr+i) . is is is . is

is

equivalent to *(&arr[0]) or arr[0] equivalent to *(&arr[1]) equivalent to *(&arr[2]) equivalent to *(&arr[3]) or arr[1] or arr[2] or arr[3]

equivalent to *(&arr[i])

or arr[i]

You will be surprised to know that internally the C/C++ compiler converts the arr[i] to *(arr+i). This means that all the following notations are same:

arr[i] *(arr+i) *(i+arr) i[arr]

Following program shows this fact.

/* Program - 4.c */ #include main() { int arr[5] = {10, 20, 30, 40, 50}; int i;

for(i=0; i<5; i++)

printf("\nAddress : %u contains a value : %d %d %d %d", (arr+i), arr[i], *(arr+i), *(i+arr), i[arr]); }

When we run this program, we get the following output.

Address : 65516 contains a value : 10 10 10 10

Address : 65518 contains a value : 20 20 20 20

Address : 65520 contains a value : 30 30 30 30

Address : 65522 contains a value : 40 40 40 40

Address : 65524 contains a value : 50 50 50 50

Although array names and pointers have strong similarity, but array names are not variables. Thus if arr is an array name and ptr is an integer pointer variable as:

ptr = arr;

then the statement

ptr++

is completely valid, but the statement

arr++

is completely invalid. It is so because array names are constant pointers whose values can not be changed. If you try this then it will mean that you are attempting to change the base address of an array. And fortunately the C compiler would never allow this.

Another main difference between arrays and pointers is the way sizeof operator treats them. It means that if arr is an array name and ptr is an integer pointer as:

ptr = arr; then sizeof (arr)

would result in total number of memory occupied by array elements and

sizeof(ptr)

would result in 2 because the size of any pointer variable is 2 bytes.

Pointers and Two Dimensional Arrays


Two-dimensional arrays are arrays with two dimensions, namely rows and columns. Each row of a two dimensional array can be thought as one dimensional array. This is very important fact if we wish to access elements of a two-dimensional arrays using pointer.

Let we have following two dimensional array:

int num[4][3] = {

{210, 614, 127},

{174, 443, 242},

{161, 820, 667},

{511, 203, 200} };

can be though of as setting up a one dimensional array of 4 elements, each of which is a one dimensional array of 3 elements. Since each row of the two dimensional array is treated as a one dimensional array,

therefore the name of the array points to the starting address (base address) of the array. If we suppose that array elements are stored in memory in the row major form as shown in figure-3 then the expression num[0] points to the 0th row, num[1] points to the 1st row and so on. In other words, you can say that num[i] points to the ith row of the array.

Figure 3

Now we will see how to access the element num[i][j] using pointers. We know that num[i] gives the address of ith one dimensional array. Therefore num[i]+j points to the jth element in the ith row of the array. And the value at this address can be obtained by using the value at address operator as:

*( num[i]+j)

But earlier we have seen that num[i] is same as *(num+i). Therefore the expression

*( num[i]+j)

is equivalent to

*(*( num+i)+j)

Thus all the following notations refer to the same element:

num[i][j] *( num[i]+j) *(*( num+i)+j)

Following program illustrates these concepts.

/* Program - 5.c */ #include main() { int num[4][3] = { {210, 614, 127}, {174, 443, 242}, {161, 820, 667}, {511, 203, 200} }; int i; for(i=0; i<4; i++) { for(j=0; j<3; j++) printf("\nAddress : %u contains the value : %d %d %d", num[i]+j, num[i][j], *(num[i]+j),*(*(num+i)+j)); } }

Here is the output of this program.

Address : 65502 contains the value : 210 210 210 Address : 65504 contains the value : 614 614 614 Address : 65506 contains the value : 127 127 127 Address : 65508 contains the value : 174 174 174 Address : 65510 contains the value : 443 443 443 Address : 65512 contains the value : 242 242 242 Address : 65514 contains the value : 161 161 161 Address : 65516 contains the value : 820 820 820 Address : 65518 contains the value : 667 667 667 Address : 65520 contains the value : 511 511 511 Address : 65522 contains the value : 203 203 203 Address : 65524 contains the value : 200 200 200

Pointers and Three Dimensional Arrays


Three-dimensional arrays are arrays of two dimensional arrays. For example, let we have a three dimensional array with dimensions (3, 2, 4) as follows:

int num[3][2][4] = { { {10, 14, 12, 15}, {17, 43, 22, 18} }, { {11, 20, 24, 66}, {50, 44, 23, 20} }, { {90, 94, 112, 75}, {67, 31, 32, 28}

} };

Since the array name points to the starting address (base address) of three dimensional array. The array name, num, with a single script i gives the starting address of the ith two-dimensional array. Thus num[i] is the address of the ith two dimensional array. Similarly num[i][j] would give the starting address of the jth row of the ith two dimensional array. Finally (num[i][j]+k) gives the address of the kth element in the jth row of the ith two dimensional array. And the value at this address can be obtained by using the value at address operator as:

*( num[i][j]+k)

This expression can be equivalent to the following expressions:

*( *(num[i]+j)+k) *( *(*(num+i)+j)+k)

Using these concepts, the following program displays each element of a three dimensional array using pointers.

/* Program -6.c */ #include main() { int i, j, k; int num[3][2][4] = { { {10, 14, 12, 15},

{17, 43, 22, 18} }, { {11, 20, 24, 66}, {50, 44, 23, 20} }, { {90, 94, 112, 75}, {67, 31, 32, 28} } }; for(i=0; i<3; i++) { for(j=0; j<2; j++) { for(k=0; k<4; k++) { printf("\nAddress : %u contains value : %d\t %d\t %d\t", (num[i][j]+k), num[i][j][k], *(num[i][j]+k), *(*(num[i]+j)+k),

*(*(*(num+i)+j)+k); } } } }

When you run this program, you get following output.

Address : 65476 contains value : 10 Address : 65478 contains value : 14

10 14

10 14

10 14

Address : 65480 contains value : 12 Address : 65482 contains value : 15 Address : 65484 contains value : 17 Address : 65486 contains value : 43 Address : 65488 contains value : 22 Address : 65490 contains value : 18 Address : 65492 contains value : 11 Address : 65494 contains value : 20 Address : 65496 contains value : 24 Address : 65498 contains value : 66 Address : 65500 contains value : 50 Address : 65502 contains value : 44 Address : 65504 contains value : 23 Address : 65506 contains value : 20 Address : 65508 contains value : 90 Address : 65510 contains value : 94 Address : 65512 contains value : 112 Address : 65514 contains value : 75 Address : 65516 contains value : 67 Address : 65518 contains value : 31 Address : 65520 contains value : 32 Address : 65522 contains value : 28

12 15 17 43 22 18 11 20 24 66 50 44 23 20 90 94 112 75 67 31 32 28

12 15 17 43 22 18 11 20 24 66 50 44 23 20 90 94 112 75 67 31 32 28

12 15 17 43 22 18 11 20 24 66 50 44 23 20 90 94 112 75 67 31 32 28

Array of Pointers
An array of pointers is similar to an array of any other data type. An array of pointers is a collection of addresses. The addresses present in an array of pointers can be addresses of isolated variables or of array elements or any other addresses.

Let we have an array of 5 integers as:

int arr[5] = {10, 20, 30, 40, 50};

then we can have an array of pointers ptr as:

int *ptr[5] = {arr, arr+1, arr+2, arr+3, arr+4, arr+5};

Here ptr[0] will contain the address of first element of array arr, ptr[1] of second element of array arr and so on. Following table shows:

ptr[0] = (arr+0); ptr[1] = (arr+1); ptr[2] = (arr+2); ptr[3] = (arr+3); ptr[4] = (arr+4);

Let first element of an array of integer arr is stored at address 65516 then the successive elements of the array arr are stored in successive memory location. Figure-4 shows the memory representation of the array of pointers, ptr and an integer array, arr.

Figure 4

Remember that an array of pointers can also contain addresses of isolated variables. Following code segment illustrates this fact.

int a, b, c, d, e; int *ptr[5]; ptr[0] = &a; ptr[1] = &b; ptr[2] = &c; ptr[3] = &d; ptr[4] = &e;

You can say that all rules that apply to an array of basic data type apply to the array of pointers as well.

C++ Pointers Concept of Pointers:


Every storage location of memory has an associated address. Address is a number that grows sequentially. For every program placed in memory, each variable or function in the program has an associated address. Sponsored Links

The address of operator:


The address of operator or Reference operator is denoted by the notation &. When the user wants to get the address of a variable, then the reference operator & can be used. The operator & is used to find the address associated with a variable. The syntax of the reference operator is as follows: &variablename

This means that the address of the variablename is achieved. For Example

#include <iostream.h> void main() { int exf=200; int test=300; cout<<endl<<&exf <<endl<<&test; } The output of the above program is: 0x92343456 0x78252348 The &exf has the address associated with the integer variable exf and the &test has the address associated with the integer variable test which are displayed using the cout statement. Using the understanding of address of operators, the discussion turns to the concept of pointers. exforsys test x = &exforsys; = 100; exforsys;

Using the above information, the assignment takes place as below:

exforsys is an integer variable having the value of 100 stored in memory address location 3501. When the variable exforsys is assigned to the variable test in the second statement: test = exforsys;

The value of the variable exforsys 100 is copied to the variable test. In the third statement, the address of the variable exforsys is denoted by reference operator &exforsys is assigned to the variable x as: x = &exforsys; The address of the variable 3501 and not the contents of the variable exforsys is copied into the variable x. The pointers concept fits in this statement. Pointers are the variable that store the reference to another variable. Pointers are variables that store the address of the variable that it is pointed by. Variable x is referred to as the pointer in the above example. The programmer must note that the address operator placed before a variable is not the same as operator & placed after the variable. For example, &x is not same as x&. Variable &x refers to address operator whereas x& refer to reference operator&. Pointer is a variable that holds the address, also called pointer variable.

Defining Pointer Variables or Pointer:


In order to define pointer variables, the programmer must use the operator denoted as * in C++. The symbol * when placed before a pointer, variable means that it as a pointer to. While defining variables, the data type is placed before it. When the programmer wants to define the integer variable i it is written: int i; A programmer may think that to define pointer variable there is a separate data type. But this is not the case. There is no separate data type for pointer available. When a programmer defines a pointer variable, he or she can point to integer, float, char. The compiler must know the type of data the pointer is pointing to. To define pointer variable is as follows: datatype_of_ variable_pointedto* pointer_varaible; Sponsored Links For example: char* ch; This defines that ch is a pointer variable which points to char data type. int* i;

This defines that i is a pointer variable which points to int data type. float* f; This defines that f is a pointer variable which points to float data type.

Pointers
We have already seen how variables are seen as memory cells that can be accessed using their identifiers. This way we did not have to care about the physical location of our data within memory, we simply used its identifier whenever we wanted to refer to our variable. The memory of your computer can be imagined as a succession of memory cells, each one of the minimal size that computers manage (one byte). These single-byte memory cells are numbered in a consecutive way, so as, within any block of memory, every cell has the same number as the previous one plus one. This way, each cell can be easily located in the memory because it has a unique address and all the memory cells follow a successive pattern. For example, if we are looking for cell 1776 we know that it is going to be right between cells 1775 and 1777, exactly one thousand cells after 776 and exactly one thousand cells before cell 2776.
Last update on Sep 29, 2009 at 10:53am UTC

Published by Juan Soulie

Reference operator (&)


As soon as we declare a variable, the amount of memory needed is assigned for it at a specific location in memory (its memory address). We generally do not actively decide the exact location of the variable within the panel of cells that we have imagined the memory to be - Fortunately, that is a task automatically performed by the operating system during runtime. However, in some cases we may be interested in knowing the address where our variable is being stored during runtime in order to operate with relative positions to it. The address that locates a variable within memory is what we call a reference to that variable. This reference to a variable can be obtained by preceding the identifier of a variable with an ampersand sign (&), known as reference operator, and which can be literally translated as "address of". For example:

ted = &andy;

This would assign to ted the address of variable andy, since when preceding the name of the variable andy with the reference operator (&) we are no longer talking about the content of the variable itself, but about its reference (i.e., its address in memory). From now on we are going to assume that andy is placed during runtime in the memory

address 1776. This number (1776) is just an arbitrary assumption we are inventing right now in order to help clarify some concepts in this tutorial, but in reality, we cannot know before runtime the real value the address of a variable will have in memory. Consider the following code fragment:

1 2 andy = 3 25; fred = andy; ted = &andy;

The values contained in each variable after the execution of this, are shown in the following diagram:

First, we have assigned the value 25 to andy (a variable whose address in memory we have assumed to be 1776). The second statement copied to fred the content of variable andy (which is 25). This is a standard assignment operation, as we have done so many times before. Finally, the third statement copies to ted not the value contained in andy but a reference to it (i.e., its address, which we have assumed to be 1776). The reason is that in this third assignment operation we have preceded the identifier andy with the reference operator (&), so we were no longer referring to the value of andy but to its reference (its address in memory). The variable that stores the reference to another variable (like ted in the previous example) is what we call a pointer. Pointers are a very powerful feature of the C++ language that has many uses in advanced programming. Farther ahead, we will see how this type of variable is used and declared.

Dereference operator (*)


We have just seen that a variable which stores a reference to another variable is called a pointer. Pointers are said to "point to" the variable whose reference they store. Using a pointer we can directly access the value stored in the variable which it points to. To do this, we simply have to precede the pointer's identifier with an asterisk (*), which acts as dereference operator and that can be literally translated to "value pointed by".

Therefore, following with the values of the previous example, if we write:

beth = *ted;

(that we could read as: "beth equal to value pointed by ted") beth would take the value 25, since ted is 1776, and the value pointed by 1776 is 25.

You must clearly differentiate that the expression ted refers to the value 1776, while *ted (with an asterisk * preceding the identifier) refers to the value stored at address 1776, which in this case is 25. Notice the difference of including or not including the dereference operator (I have included an explanatory commentary of how each of these two expressions could be read):

1 2 beth = ted; beth = *ted; ( 25 )

// beth equal to ted ( 1776 ) // beth equal to value pointed by ted

Notice the difference between the reference and dereference operators:

& is the reference operator and can be read as "address of" * is the dereference operator and can be read as "value pointed by"

Thus, they have complementary (or opposite) meanings. A variable referenced with & can be dereferenced with *. Earlier we performed the following two assignment operations:

1 2 andy = 25;

ted = &andy;

Right after these two statements, all of the following expressions would give true as result:

1 2 andy == 25 3 4 &andy == 1776 ted == 1776 *ted == 25

The first expression is quite clear considering that the assignment operation performed on andy was andy=25. The second one uses the reference operator (&), which returns the address of variable andy, which we assumed it to have a value of 1776. The third one is somewhat obvious since the second expression was true and the assignment operation performed on ted was ted=&andy. The fourth expression uses the dereference operator (*) that, as we have just seen, can be read as "value pointed by", and the value pointed by ted is indeed 25. So, after all that, you may also infer that for as long as the address pointed by ted remains unchanged the following expression will also be true:

*ted == andy

Declaring variables of pointer types


Due to the ability of a pointer to directly refer to the value that it points to, it becomes necessary to specify in its declaration which data type a pointer is going to point to. It is not the same thing to point to a char as to point to an int or a float. The declaration of pointers follows this format:

type * name;
where type is the data type of the value that the pointer is intended to point to. This type is not the type of the pointer itself! but the type of the data the pointer points to. For example:

1 2 int * number;

3 char * character; float * greatnumber;

These are three declarations of pointers. Each one is intended to point to a different data type, but in fact all of them are pointers and all of them will occupy the same amount of space in memory (the size in memory of a pointer depends on the platform where the code is going to run). Nevertheless, the data to which they point to do not occupy the same amount of space nor are of the same type: the first one points to an int, the second one to a char and the last one to a float. Therefore, although these three example variables are all of them pointers which occupy the same size in memory, they are said to have different types: int*, char* and float* respectively, depending on the type they point to. I want to emphasize that the asterisk sign (*) that we use when declaring a pointer only means that it is a pointer (it is part of its type compound specifier), and should not be confused with the dereference operator that we have seen a bit earlier, but which is also written with an asterisk (*). They are simply two different things represented with the same sign. Now have a look at this code:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17

// my first pointer #include <iostream> using namespace std;

firstvalue is 10 secondvalue is 20

int main () { int firstvalue, secondvalue; int * mypointer;

mypointer = &firstvalue; *mypointer = 10; mypointer = &secondvalue; *mypointer = 20; cout << "firstvalue is " <<

firstvalue << endl; cout << "secondvalue is " << secondvalue << endl; return 0; }

Notice that even though we have never directly set a value to either firstvalue or secondvalue, both end up with a value set indirectly through the use of mypointer. This is the procedure: First, we have assigned as value of mypointer a reference to firstvalue using the reference operator (&). And then we have assigned the value 10 to the memory location pointed by mypointer, that because at this moment is pointing to the memory location of firstvalue, this in fact modifies the value of firstvalue. In order to demonstrate that a pointer may take several different values during the same program I have repeated the process with secondvalue and that same pointer, mypointer. Here is an example a little bit more elaborated:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20

// more pointers #include <iostream> using namespace std;

firstvalue is 10 secondvalue is 20

int main () { int firstvalue = 5, secondvalue = 15; int * p1, * p2;

p1 = &firstvalue; // p1 = address of firstvalue p2 = &secondvalue; // p2 = address of secondvalue *p1 = 10; pointed by p1 = 10 // value

*p2 = *p1; // value pointed by p2 = value pointed by p1 p1 = p2; // p1 = p2 (value of pointer is copied) *p1 = 20; pointed by p1 = 20 // value

cout << "firstvalue is " << firstvalue << endl; cout << "secondvalue is " << secondvalue << endl; return 0; }

I have included as a comment on each line how the code can be read: ampersand (&) as "address of" and asterisk (*) as "value pointed by". Notice that there are expressions with pointers p1 and p2, both with and without dereference operator (*). The meaning of an expression using the dereference operator (*) is very different from one that does not: When this operator precedes the pointer name, the expression refers to the value being pointed, while when a pointer name appears without this operator, it refers to the value of the pointer itself (i.e. the address of what the pointer is pointing to). Another thing that may call your attention is the line:

int * p1, * p2;

This declares the two pointers used in the previous example. But notice that there is an asterisk (*) for each pointer, in order for both to have type int* (pointer to int). Otherwise, the type for the second variable declared in that line would have been int (and not int*) because of precedence relationships. If we had written:

int * p1, p2;

p1 would indeed have int* type, but p2 would have type int (spaces do not matter at all for
this purpose). This is due to operator precedence rules. But anyway, simply remembering that you have to put one asterisk per pointer is enough for most pointer users.

Pointers and arrays


The concept of array is very much bound to the one of pointer. In fact, the identifier of an array is equivalent to the address of its first element, as a pointer is equivalent to the address of the first element that it points to, so in fact they are the same concept. For example, supposing these two declarations:

1 2 int numbers [20]; int * p;

The following assignment operation would be valid:

p = numbers;

After that, p and numbers would be equivalent and would have the same properties. The only difference is that we could change the value of pointer p by another one, whereas numbers will always point to the first of the 20 elements of type int with which it was defined. Therefore, unlike p, which is an ordinary pointer, numbers is an array, and an array can be considered a constant pointer. Therefore, the following allocation would not be valid:

numbers = p;

Because numbers is an array, so it operates as a constant pointer, and we cannot assign values to constants. Due to the characteristics of variables, all expressions that include pointers in the following example are perfectly valid:

1 2 // more pointers 3 4 #include <iostream> 5 6 using namespace std; 7 8 9 10

10, 20, 30, 40, 50,

11 12 int main () 13 14 { 15 int numbers[5]; 16 17 int * p; p = numbers; p++; *p = 20; *p = 30; *p = 40; *p = 10;

p = &numbers[2]; p = numbers + 3; p = numbers;

*(p+4) = 50;

for (int n=0; n<5; n++) cout << numbers[n] << ", "; return 0; }

In the chapter about arrays we used brackets ([]) several times in order to specify the index of an element of the array to which we wanted to refer. Well, these bracket sign operators [] are also a dereference operator known as offset operator. They dereference the variable they follow just as * does, but they also add the number between brackets to the address being dereferenced. For example:

1 2 a[5] = 0; 0 *(a+5) = 0; = 0

// a [offset of 5] = // pointed by (a+5)

These two expressions are equivalent and valid both if a is a pointer or if a is an array.

Pointer initialization
When declaring pointers we may want to explicitly specify which variable we want them to point to:

1 2 int number;

int *tommy = &number;

The behavior of this code is equivalent to:

1 2 int number; 3 int *tommy; tommy = &number;

When a pointer initialization takes place we are always assigning the reference value to where the pointer points (tommy), never the value being pointed (*tommy). You must consider that at the moment of declaring a pointer, the asterisk (*) indicates only that it is a pointer, it is not the dereference operator (although both use the same sign: *). Remember, they are two different functions of one sign. Thus, we must take care not to confuse the previous code with:

1 2 int number; 3 int *tommy; *tommy = &number;

that is incorrect, and anyway would not have much sense in this case if you think about it. As in the case of arrays, the compiler allows the special case that we want to initialize the content at which the pointer points with constants at the same moment the pointer is declared:

char * terry = "hello";

In this case, memory space is reserved to contain "hello" and then a pointer to the first character of this memory block is assigned to terry. If we imagine that "hello" is stored at the memory locations that start at addresses 1702, we can represent the previous declaration as:

It is important to indicate that terry contains the value 1702, and not 'h' nor "hello", although 1702 indeed is the address of both of these. The pointer terry points to a sequence of characters and can be read as if it was an array (remember that an array is just like a constant pointer). For example, we can access the fifth element of the array with any of these two expression:

1 2 *(terry +4) terry[4 ]

Both expressions have a value of 'o' (the fifth element of the array).

Pointer arithmetics
To conduct arithmetical operations on pointers is a little different than to conduct them on regular integer data types. To begin with, only addition and subtraction operations are allowed to be conducted with them, the others make no sense in the world of pointers. But both addition and subtraction have a different behavior with pointers according to the size of the data type to which they point. When we saw the different fundamental data types, we saw that some occupy more or less space than others in the memory. For example, let's assume that in a given compiler for a specific machine, char takes 1 byte, short takes 2 bytes and long takes 4. Suppose that we define three pointers in this compiler:

1 2 char 3 *mychar; short *myshort; long *mylong;

and that we know that they point to memory locations 1000, 2000 and 3000 respectively.

So if we write:

1 2 mychar+ 3 +; myshort ++; mylong+ +;

mychar, as you may expect, would contain the value 1001. But not so obviously, myshort would contain the value 2002, and mylong would contain 3004, even though they have each

been increased only once. The reason is that when adding one to a pointer we are making it to point to the following element of the same type with which it has been defined, and therefore the size in bytes of the type pointed is added to the pointer.

This is applicable both when adding and subtracting any number to a pointer. It would happen exactly the same if we write:

1 2 mychar = mychar + 3 1; myshort = myshort + 1; mylong = mylong + 1;

Both the increase (++) and decrease (--) operators have greater operator precedence than the dereference operator (*), but both have a special behavior when used as suffix (the expression

is evaluated with the value it had before being increased). Therefore, the following expression may lead to confusion:

* p + +

Because ++ has greater precedence than *, this expression is equivalent to *(p++). Therefore, what it does is to increase the value of p (so it now points to the next element), but because ++ is used as postfix the whole expression is evaluated as the value pointed by the original reference (the address the pointer pointed to before being increased). Notice the difference with:

(*p)++
Here, the expression would have been evaluated as the value pointed by p increased by one. The value of p (the pointer itself) would not be modified (what is being modified is what it is being pointed to by this pointer). If we write:

*p++ = *q++;

Because ++ has a higher precedence than *, both p and q are increased, but because both increase operators (++) are used as postfix and not prefix, the value assigned to *p is *q before both p and q are increased. And then both are increased. It would be roughly equivalent to:

1 2 *p = 3 *q; ++p; ++q;

Like always, I recommend you to use parentheses () in order to avoid unexpected results and to give more legibility to the code.

Pointers to pointers
C++ allows the use of pointers that point to pointers, that these, in its turn, point to data (or even to other pointers). In order to do that, we only need to add an asterisk (*) for each level of reference in their declarations:

1 2 char a; 3 4 char * 5 b; 6 char ** c; a = 'z'; b = &a; c = &b;

This, supposing the randomly chosen memory locations for each variable of 7230, 8092 and 10502, could be represented as:

The value of each variable is written inside each cell; under the cells are their respective addresses in memory. The new thing in this example is variable c, which can be used in three different levels of indirection, each one of them would correspond to a different value:

c has type char** and a value of 8092 *c has type char* and a value of 7230 **c has type char and a value of 'z'

void pointers
The void type of pointer is a special type of pointer. In C++, void represents the absence of type, so void pointers are pointers that point to a value that has no type (and thus also an undetermined length and undetermined dereference properties). This allows void pointers to point to any data type, from an integer value or a float to a string of characters. But in exchange they have a great limitation: the data pointed by them cannot be directly dereferenced (which is logical, since we have no type to dereference to), and for that reason we will always have to cast the address in the void pointer to some other pointer type that points to a concrete data type before dereferencing it. One of its uses may be to pass generic parameters to a function:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21

// increaser #include <iostream> using namespace std;

y, 1603

void increase (void* data, int psize) { if ( psize == sizeof(char) ) { char* pchar; pchar=(char*)data; ++ (*pchar); } ) else if (psize == sizeof(int)

{ int* pint; pint=(int*)data; ++(*pint); } }

int main () { char a = 'x'; int b = 1602; increase (&a,sizeof(a)); increase (&b,sizeof(b)); cout << a << ", " << b << endl; return 0; }

sizeof is an operator integrated in the C++ language that returns the size in bytes of its
parameter. For non-dynamic data types this value is a constant. Therefore, for example, sizeof(char) is 1, because char type is one byte long.

Null pointer

A null pointer is a regular pointer of any pointer type which has a special value that indicates that it is not pointing to any valid reference or memory address. This value is the result of typecasting the integer value zero to any pointer type.

1 2 int * p; p = 0; value // p has a null pointer

Do not confuse null pointers with void pointers. A null pointer is a value that any pointer may take to represent that it is pointing to "nowhere", while a void pointer is a special type of pointer that can point to somewhere without a specific type. One refers to the value stored in the pointer itself and the other to the type of data it points to.

Pointers to functions
C++ allows operations with pointers to functions. The typical use of this is for passing a function as an argument to another function, since these cannot be passed dereferenced. In order to declare a pointer to a function we have to declare it like the prototype of the function except that the name of the function is enclosed between parentheses () and an asterisk (*) is inserted before the name:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27

// pointer to functions #include <iostream> using namespace std;

int addition (int a, int b) { return (a+b); }

int subtraction (int a, int b) { return (a-b); }

int operation (int x, int y, int (*functocall)(int,int)) { int g; g = (*functocall)(x,y);

return (g); }

int main () { int m,n; int (*minus)(int,int) = subtraction;

m = operation (7, 5, addition); n = operation (20, m, minus); cout <<n; return 0; }

In the example, minus is a pointer to a function that has two parameters of type int. It is immediately assigned to point to the function subtraction, all in a single line:

int (* minus)(int,int) = subtraction;

You might also like