C++ Overloading (Operator and Function)
C++ Overloading (Operator and Function)
C++ allows you to specify more than one definition for a function name or
an operator in the same scope, which is called function overloading and operator
overloading respectively.
An overloaded declaration is a declaration that is declared with the same name as a
previously declared declaration in the same scope, except that both declarations have
different arguments and obviously different definition (implementation).
When you call an overloaded function or operator, the compiler determines the most
appropriate definition to use, by comparing the argument types you have used to call
the function or operator with the parameter types specified in the definitions. The
process of selecting the most appropriate overloaded function or operator is
called overload resolution.
#include <iostream>
using namespace std;
class printData {
public:
void print(int i) {
cout << "Printing int: " << i << endl;
}
void print(double f) {
cout << "Printing float: " << f << endl;
}
void print(char* c) {
cout << "Printing character: " << c << endl;
}
};
int main(void) {
printData pd;
return 0;
}
When the above code is compiled and executed, it produces the following result −
Printing int: 5
Printing float: 500.263
Printing character: Hello C++
Overloadable/Non-overloadableOperators
Following is the list of operators which can be overloaded −
+ - * / % ^
& | ~ ! , =
+= -= /= %= ^= &=
|= *= <<= >>= [] ()
:: .* . ?:
Things to remember
1. Operator overloading allows you to redefine the way operator works for user-
defined types only (objects, structures). It cannot be used for built-in types (int, float,
char etc.).
2. Two operators = and & are already overloaded by default in C++. For example:
To copy objects of same class, you can directly use = operator. You do not need to
create an operator function.
3. Operator overloading cannot change the precedence and associatively of
operators. However, if you want to change the order of evaluation, parenthesis should
be used.
4. There are 4 operators that cannot be overloaded in C++. They are :: (scope
resolution), . (member selection), .* (member selection through pointer to function)
and ?: (ternary operator).
INHERITANCE
yes
Accessible from derived (inherited as protected
class? no yes variables)
yes yes
Accessible from derived (inherited as private (inherited as private
class? no variables) variables)
Type of Inheritance
When deriving a class from a base class, the base class may be inherited
through public, protected or private inheritance. The type of inheritance is specified
by the access-specifier as explained above.
We hardly use protected or private inheritance, but public inheritance is commonly
used. While using different type of inheritance, following rules are applied −
Public Inheritance − When deriving a class from a public base class, public members of
the base class become public members of the derived class and protected members of
the base class become protected members of the derived class. A base
class's private members are never accessible directly from a derived class, but can be
accessed through calls to the public and protected members of the base class.
Protected Inheritance − When deriving from a protected base
class, public and protected members of the base class become protected members of
the derived class.
Private Inheritance − When deriving from a private base
class, public and protected members of the base class become private members of the
derived class.
TYPES
Single, multiple, multilevel, hierarchical and hybrid inheritance
Multiple Inheritance
A C++ class can inherit members from more than one class and here is the extended
syntax −
class derived-class: access baseA, access baseB....
Where access is one of public, protected, or private and would be given for every
base class and they will be separated by comma as shown above. Let us try the
following example −
#include <iostream>
protected:
int width;
int height;
};
// Base class PaintCost
class PaintCost {
public:
int getCost(int area) {
return area * 70;
}
};
// Derived class
class Rectangle: public Shape, public PaintCost {
public:
int getArea() {
return (width * height);
}
};
int main(void) {
Rectangle Rect;
int area;
Rect.setWidth(5);
Rect.setHeight(7);
area = Rect.getArea();
return 0;
}
When the above code is compiled and executed, it produces the following result −
Total area: 35
Total paint cost: $2450
Object
This is the basic unit of object oriented programming. That is both data and function
that operate on data are bundled as a unit called as object.
Class
When you define a class, you define a blueprint for an object. This doesn't actually
define any data, but it does define what the class name means, that is, what an object
of the class will consist of and what operations can be performed on such an object.
Abstraction
Data abstraction refers to, providing only essential information to the outside world and
hiding their background details, i.e., to represent the needed information in program
without presenting the details.
For example, a database system hides certain details of how data is stored and
created and maintained. Similar way, C++ classes provides different methods to the
outside world without giving internal detail about those methods and data.
Encapsulation
Encapsulation is placing the data and the functions that work on that data in the same
place. While working with procedural languages, it is not always clear which functions
work on which variables but object-oriented programming provides you framework to
place the data and the relevant functions together in the same object.
Inheritance
One of the most useful aspects of object-oriented programming is code reusability. As
the name suggests Inheritance is the process of forming a new class from an existing
class that is from the existing class called as base class, new class is formed called as
derived class.
This is a very important concept of object-oriented programming since this feature
helps to reduce the code size.
Polymorphism
The ability to use an operator or function in different ways in other words giving
different meaning or functions to the operators or functions is called polymorphism.
Poly refers to many. That is a single function or an operator functioning in many ways
different upon the usage is called polymorphism.
Overloading
The concept of overloading is also a branch of polymorphism. When the exiting
operator or function is made to operate on new data type, it is said to be overloaded.
Comments in C++
Program comments are explanatory statements that you can include in the C++ code.
These comments help anyone reading the source code. All programming languages
allow for some form of comments.
C++ supports single-line and multi-line comments. All characters available inside any
comment are ignored by C++ compiler.
C++ comments start with /* and end with */. For example −
/* This is a comment */
main() {
cout << "Hello World"; // prints Hello World
return 0;
}
When the above code is compiled, it will ignore // prints Hello World and final
executable will produce the following result −
Hello World
Within a /* and */ comment, // characters have no special meaning. Within a //
comment, /* and */ have no special meaning. Thus, you can "nest" one kind of
comment within the other kind. For example −
/* Comment out printing of Hello World:
*/
Type Keyword
Boolean bool
Character char
Integer int
Several of the basic types can be modified using one or more of these type modifiers −
signed
unsigned
short
long
The following table shows the variable type, how much memory it takes to store the
value in memory, and what is maximum and minimum value which can be stored in
such type of variables.
The size of variables might be different from those shown in the above table,
depending on the compiler and the computer you are using.
Following is the example, which will produce correct size of various data types on your
computer.
Live Demo
#include <iostream>
using namespace std;
int main() {
cout << "Size of char : " << sizeof(char) << endl;
cout << "Size of int : " << sizeof(int) << endl;
cout << "Size of short int : " << sizeof(short int) << endl;
cout << "Size of long int : " << sizeof(long int) << endl;
cout << "Size of float : " << sizeof(float) << endl;
cout << "Size of double : " << sizeof(double) << endl;
cout << "Size of wchar_t : " << sizeof(wchar_t) << endl;
return 0;
}
This example uses endl, which inserts a new-line character after every line and <<
operator is being used to pass multiple values out to the screen. We are also
using sizeof() operator to get size of various data types.
When the above code is compiled and executed, it produces the following result which
can vary from machine to machine −
Size of char : 1
Size of int : 4
Size of short int : 2
Size of long int : 4
Size of float : 4
Size of double : 8
Size of wchar_t : 4
typedef Declarations
You can create a new name for an existing type using typedef. Following is the simple
syntax to define a new type using typedef −
typedef type newname;
For example, the following tells the compiler that feet is another name for int −
typedef int feet;
Now, the following declaration is perfectly legal and creates an integer variable called
distance −
feet distance;
Enumerated Types
An enumerated type declares an optional type name and a set of zero or more
identifiers that can be used as values of the type. Each enumerator is a constant
whose type is the enumeration.
Creating an enumeration requires the use of the keyword enum. The general form of
an enumeration type is −
enum enum-name { list of names } var-list;
Here, the enum-name is the enumeration's type name. The list of names is comma
separated.
For example, the following code defines an enumeration of colors called colors and the
variable c of type color. Finally, c is assigned the value "blue".
enum color { red, green, blue } c;
c = blue;
By default, the value of the first name is 0, the second name has the value 1, and the
third has the value 2, and so on. But you can give a name, a specific value by adding
an initializer. For example, in the following enumeration, green will have the value 5.
enum color { red, green = 5, blue };
Here, blue will have a value of 6 because each name will be one greater than the one
that precedes it.
C++ Variable Types
A variable provides us with named storage that our programs can manipulate. Each
variable in C++ has a specific type, which determines the size and layout of the
variable's memory; the range of values that can be stored within that memory; and the
set of operations that can be applied to the variable.
The name of a variable can be composed of letters, digits, and the underscore
character. It must begin with either a letter or an underscore. Upper and lowercase
letters are distinct because C++ is case-sensitive −
There are following basic types of variable in C++ as explained in last chapter −
1
bool
Stores either value true or false.
2
char
Typically a single octet (one byte). This is an integer type.
3
int
The most natural size of integer for the machine.
4
float
A single-precision floating point value.
5
double
A double-precision floating point value.
6
void
Represents the absence of type.
7
wchar_t
A wide character type.
C++ also allows to define various other types of variables, which we will cover in
subsequent chapters like Enumeration, Pointer, Array, Reference, Data
structures, and Classes.
Following section will cover how to define, declare and use various types of variables.
Example
Try the following example where a variable has been declared at the top, but it has
been defined inside the main function −
Live Demo
#include <iostream>
using namespace std;
// Variable declaration:
extern int a, b;
extern int c;
extern float f;
int main () {
// Variable definition:
int a, b;
int c;
float f;
// actual initialization
a = 10;
b = 20;
c = a + b;
f = 70.0/3.0;
cout << f << endl ;
return 0;
}
When the above code is compiled and executed, it produces the following result −
30
23.3333
Same concept applies on function declaration where you provide a function name at
the time of its declaration and its actual definition can be given anywhere else. For
example −
// function declaration
int func();
int main() {
// function call
int i = func();
}
// function definition
int func() {
return 0;
}
Operators in C++
An operator is a symbol that tells the compiler to perform specific mathematical or
logical manipulations. C++ is rich in built-in operators and provide the following types of
operators −
Arithmetic Operators
Relational Operators
Logical Operators
Bitwise Operators
Assignment Operators
Misc Operators
This chapter will examine the arithmetic, relational, logical, bitwise, assignment and
other operators one by one.
Arithmetic Operators
There are following arithmetic operators supported by C++ language −
Assume variable A holds 10 and variable B holds 20, then −
Show Examples
Relational Operators
There are following relational operators supported by C++ language
Assume variable A holds 10 and variable B holds 20, then −
Show Examples
> Checks if the value of left operand is greater (A > B) is not true.
than the value of right operand, if yes then
condition becomes true.
>= Checks if the value of left operand is greater (A >= B) is not true.
than or equal to the value of right operand,
if yes then condition becomes true.
<= Checks if the value of left operand is less (A <= B) is true.
than or equal to the value of right operand,
if yes then condition becomes true.
Logical Operators
There are following logical operators supported by C++ language.
Assume variable A holds 1 and variable B holds 0, then −
Show Examples
Bitwise Operators
Bitwise operator works on bits and perform bit-by-bit operation. The truth tables for &, |,
and ^ are as follows −
0 0 0 0 0
0 1 0 1 1
1 1 1 1 0
1 0 0 1 1
Assume if A = 60; and B = 13; now in binary format they will be as follows −
A = 0011 1100
B = 0000 1101
-----------------
A&B = 0000 1100
A|B = 0011 1101
A^B = 0011 0001
~A = 1100 0011
The Bitwise operators supported by C++ language are listed in the following table.
Assume variable A holds 60 and variable B holds 13, then −
Show Examples
| Binary OR Operator copies a bit if it exists (A | B) will give 61 which is 0011 1101
in either operand.
~ Binary Ones Complement Operator is unary (~A ) will give -61 which is 1100 0011 in 2's
and has the effect of 'flipping' bits. complement form due to a signed binary
number.
Assignment Operators
There are following assignment operators supported by C++ language −
Show Examples
Misc Operators
The following table lists some other operators that C++ supports.
1
sizeof
sizeof operator returns the size of a variable. For example, sizeof(a), where ‘a’ is integer, and
will return 4.
2
Condition ? X : Y
Conditional operator (?). If Condition is true then it returns value of X otherwise returns value
of Y.
3
,
Comma operator causes a sequence of operations to be performed. The value of the entire
comma expression is the value of the last expression of the comma-separated list.
4
. (dot) and -> (arrow)
Member operators are used to reference individual members of classes, structures, and
unions.
5
Cast
Casting operators convert one data type to another. For example, int(2.2000) would return 2.
6
&
Pointer operator & returns the address of a variable. For example &a; will give actual address
of the variable.
7
*
Pointer operator * is pointer to a variable. For example *var; will pointer to a variable var.
1 if statement
2 if...else statement
An ‘if’ statement can be followed by an optional ‘else’ statement, which executes when the
boolean expression is false.
3 switch statement
A ‘switch’ statement allows a variable to be tested for equality against a list of values.
4 nested if statements
You can use one ‘if’ or ‘else if’ statement inside another ‘if’ or ‘else if’ statement(s).
The ? : Operator
We have covered conditional operator “? :” in previous chapter which can be used to
replace if...else statements. It has the following general form −
Exp1 ? Exp2 : Exp3;
Exp1, Exp2, and Exp3 are expressions. Notice the use and placement of the colon.
The value of a ‘?’ expression is determined like this: Exp1 is evaluated. If it is true, then
Exp2 is evaluated and becomes the value of the entire ‘?’ expression. If Exp1 is false,
then Exp3 is evaluated and its value becomes the value of the expression.
C++ programming language provides the following type of loops to handle looping
requirements.
Repeats a statement or group of statements while a given condition is true. It tests the
condition before executing the loop body.
2 for loop
Execute a sequence of statements multiple times and abbreviates the code that manages the
loop variable.
3 do...while loop
Like a ‘while’ statement, except that it tests the condition at the end of the loop body.
4 nested loops
You can use one or more loop inside any another ‘while’, ‘for’ or ‘do..while’ loop.
1 break statement
2 continue statement
Causes the loop to skip the remainder of its body and immediately retest its condition prior to
reiterating.
3 goto statement
Transfers control to the labeled statement. Though it is not advised to use goto statement in
your program.
int main () {
for( ; ; ) {
printf("This loop will run forever.\n");
}
return 0;
}
When the conditional expression is absent, it is assumed to be true. You may have an
initialization and increment expression, but C++ programmers more commonly use the
‘for (;;)’ construct to signify an infinite loop.
C++ Functions
A function is a group of statements that together perform a task. Every C++ program
has at least one function, which is main(), and all the most trivial programs can define
additional functions.
You can divide up your code into separate functions. How you divide up your code
among different functions is up to you, but logically the division usually is such that
each function performs a specific task.
A function declaration tells the compiler about a function's name, return type, and
parameters. A function definition provides the actual body of the function.
The C++ standard library provides numerous built-in functions that your program can
call. For example, function strcat() to concatenate two strings, function memcpy() to
copy one memory location to another location and many more functions.
A function is known with various names like a method or a sub-routine or a procedure
etc.
Defining a Function
The general form of a C++ function definition is as follows −
return_type function_name( parameter list ) {
body of the function
}
A C++ function definition consists of a function header and a function body. Here are
all the parts of a function −
Return Type − A function may return a value. The return_type is the data type of the value
the function returns. Some functions perform the desired operations without returning a
value. In this case, the return_type is the keyword void.
Function Name − This is the actual name of the function. The function name and the
parameter list together constitute the function signature.
Parameters − A parameter is like a placeholder. When a function is invoked, you pass a
value to the parameter. This value is referred to as actual parameter or argument. The
parameter list refers to the type, order, and number of the parameters of a function.
Parameters are optional; that is, a function may contain no parameters.
Function Body − The function body contains a collection of statements that define what the
function does.
Example
Following is the source code for a function called max(). This function takes two
parameters num1 and num2 and return the biggest of both −
// function returning the max between two numbers
return result;
}
Function Declarations
A function declaration tells the compiler about a function name and how to call the
function. The actual body of the function can be defined separately.
A function declaration has the following parts −
return_type function_name( parameter list );
For the above defined function max(), following is the function declaration −
int max(int num1, int num2);
Parameter names are not important in function declaration only their type is required,
so following is also valid declaration −
int max(int, int);
Function declaration is required when you define a function in one source file and you
call that function in another file. In such case, you should declare the function at the top
of the file calling the function.
Calling a Function
While creating a C++ function, you give a definition of what the function has to do. To
use a function, you will have to call or invoke that function.
When a program calls a function, program control is transferred to the called function.
A called function performs defined task and when it’s return statement is executed or
when its function-ending closing brace is reached, it returns program control back to
the main program.
To call a function, you simply need to pass the required parameters along with function
name, and if function returns a value, then you can store returned value. For example
−
Live Demo
#include <iostream>
using namespace std;
// function declaration
int max(int num1, int num2);
int main () {
// local variable declaration:
int a = 100;
int b = 200;
int ret;
return 0;
}
return result;
}
I kept max() function along with main() function and compiled the source code. While
running final executable, it would produce the following result −
Max value is : 200
Function Arguments
If a function is to use arguments, it must declare variables that accept the values of the
arguments. These variables are called the formal parameters of the function.
The formal parameters behave like other local variables inside the function and are
created upon entry into the function and destroyed upon exit.
While calling a function, there are two ways that arguments can be passed to a
function −
1 Call by Value
This method copies the actual value of an argument into the formal parameter of the function.
In this case, changes made to the parameter inside the function have no effect on the
argument.
2 Call by Pointer
This method copies the address of an argument into the formal parameter. Inside the
function, the address is used to access the actual argument used in the call. This means that
changes made to the parameter affect the argument.
3 Call by Reference
This method copies the reference of an argument into the formal parameter. Inside the
function, the reference is used to access the actual argument used in the call. This means
that changes made to the parameter affect the argument.
By default, C++ uses call by value to pass arguments. In general, this means that
code within a function cannot alter the arguments used to call the function and above
mentioned example while calling max() function used the same method.
return (result);
}
int main () {
// local variable declaration:
int a = 100;
int b = 200;
int result;
return 0;
}
When the above code is compiled and executed, it produces the following result −
Total value is :300
Total value is :120
B bn
#include <iostream>
class Line {
public:
void setLength( double len );
double getLength( void );
Line(); // This is the constructor
private:
double length;
};
return 0;
}
When the above code is compiled and executed, it produces the following result −
Object is being created
Length of line : 6
Parameterized Constructor
A default constructor does not have any parameter, but if you need, a constructor can
have parameters. This helps you to assign initial value to an object at the time of its
creation as shown in the following example −
Live Demo
#include <iostream>
private:
double length;
};
return 0;
}
When the above code is compiled and executed, it produces the following result −
Object is being created, length = 10
Length of line : 10
Length of line : 6
#include <iostream>
private:
double length;
};
return 0;
}
When the above code is compiled and executed, it produces the following result −
Object is being created
Length of line : 6
Object is being deleted
Polymorphism in C++
The word polymorphism means having many forms. Typically, polymorphism occurs
when there is a hierarchy of classes and they are related by inheritance.
C++ polymorphism means that a call to a member function will cause a different
function to be executed depending on the type of object that invokes the function.
Consider the following example where a base class has been derived by other two
classes −
#include <iostream>
using namespace std;
class Shape {
protected:
int width, height;
public:
Shape( int a = 0, int b = 0){
width = a;
height = b;
}
int area() {
cout << "Parent class area :" <<endl;
return 0;
}
};
class Rectangle: public Shape {
public:
Rectangle( int a = 0, int b = 0):Shape(a, b) { }
int area () {
cout << "Rectangle class area :" <<endl;
return (width * height);
}
};
int area () {
cout << "Triangle class area :" <<endl;
return (width * height / 2);
}
};
return 0;
}
When the above code is compiled and executed, it produces the following result −
Parent class area :
Parent class area :
The reason for the incorrect output is that the call of the function area() is being set
once by the compiler as the version defined in the base class. This is called static
resolution of the function call, or static linkage - the function call is fixed before the
program is executed. This is also sometimes called early binding because the area()
function is set during the compilation of the program.
But now, let's make a slight modification in our program and precede the declaration of
area() in the Shape class with the keyword virtual so that it looks like this −
class Shape {
protected:
int width, height;
public:
Shape( int a = 0, int b = 0) {
width = a;
height = b;
}
virtual int area() {
cout << "Parent class area :" <<endl;
return 0;
}
};
After this slight modification, when the previous example code is compiled and
executed, it produces the following result −
Rectangle class area
Triangle class area
This time, the compiler looks at the contents of the pointer instead of it's type. Hence,
since addresses of objects of tri and rec classes are stored in *shape the respective
area() function is called.
As you can see, each of the child classes has a separate implementation for the
function area(). This is how polymorphism is generally used. You have different
classes with a function of the same name, and even the same parameters, but with
different implementations.
Virtual Function
A virtual function is a function in a base class that is declared using the
keyword virtual. Defining in a base class a virtual function, with another version in a
derived class, signals to the compiler that we don't want static linkage for this function.
What we do want is the selection of the function to be called at any given point in the
program to be based on the kind of object for which it is called. This sort of operation is
referred to as dynamic linkage, or late binding.
Pure Virtual Functions
It is possible that you want to include a virtual function in a base class so that it may be
redefined in a derived class to suit the objects of that class, but that there is no
meaningful definition you could give for the function in the base class.
We can change the virtual function area() in the base class to the following −
class Shape {
protected:
int width, height;
public:
Shape(int a = 0, int b = 0) {
width = a;
height = b;
}