|
C++ Programming Tutorials
Basics of C++
Structure of a
program
Variables
Data types
Constants
Operators
Basic Input/output
Control Structures
Control Structures
Functions (I)
Functions (II)
Compound Data Types
Arrays
Character Sequences
Pointers
Dynamic Memory
Data Structures
Other Data Types
Object Oriented Programming
Classes [I]
Classes [II]
Friendship & Inheritance
Polymorphism
Advanced Concepts
Templates
Namespaces
Exceptions
Type Casting
Preprocessor Directives
C++ Standard Library
Input/output with Files
Soft Skills
Communication Skills
Leadership Skills
.........More
|
|
C++ Programming Tutorials
Classes (II)
Overloading operators
C++ incorporates the option to use standard operators to perform
operations with classes in addition to with fundamental types. For
example:
This is obviously valid code in C++, since the different
variables of the addition are all fundamental types. Nevertheless, it is not so
obvious that we could perform an operation similar to the following one:
struct {
string product;
float price;
} a, b, c;
a = b + c; |
In fact, this will cause a compilation error, since we have
not defined the behavior our class should have with addition operations.
However, thanks to the C++ feature to overload operators, we can design classes
able to perform operations using standard operators. Here is a list of all the
operators that can be overloaded:
| Overloadable operators |
+ - * / = < > += -= *= /= << >>
<<= >>= == != <= >= ++ -- % & ^ ! |
~ &= ^= |= && || %= [] () , ->* -> new
delete new[] delete[]
|
To overload an operator in order to use it with classes we
declare operator functions, which are regular functions whose names are the
operator keyword followed by the operator sign that we want to overload. The
format is:
type operator sign (parameters) { /*...*/ }
Here you have an example that overloads the addition operator (+). We are going
to create a class to store bidimensional vectors and then we are going to add
two of them: a(3,1) and b(1,2). The addition of two bidimensional vectors is an
operation as simple as adding the two x coordinates to obtain the resulting x
coordinate and adding the two y coordinates to obtain the resulting y. In this
case the result will be (3+1,1+2) = (4,3).
// vectors: overloading operators example
#include <iostream>
using namespace std;
class CVector {
public:
int x,y;
CVector () {};
CVector (int,int);
CVector operator + (CVector);
};
CVector::CVector (int a, int b) {
x = a;
y = b;
}
CVector CVector::operator+ (CVector param) {
CVector temp;
temp.x = x + param.x;
temp.y = y + param.y;
return (temp);
}
int main () {
CVector a (3,1);
CVector b (1,2);
CVector c;
c = a + b;
cout << c.x << "," << c.y;
return 0;
} |
4,3
|
It may be a little confusing to see so many times the CVector
identifier. But, consider that some of them refer to the class name (type)
CVector and some others are functions with that name (constructors must have the
same name as the class). Do not confuse them:
CVector (int, int);
// function name CVector (constructor)
CVector operator+ (CVector); // function returns a CVector |
The function operator+ of class CVector is the one that is in
charge of overloading the addition operator (+). This function can be called
either implicitly using the operator, or explicitly using the function name:
c = a + b;
c = a.operator+ (b); |
Both expressions are equivalent.
Notice also that we have included the empty constructor (without parameters) and
we have defined it with an empty block:
This is necessary, since we have explicitly declared another
constructor:
And when we explicitly declare any constructor, with any
number of parameters, the default constructor with no parameters that the
compiler can declare automatically is not declared, so we need to declare it
ourselves in order to be able to construct objects of this type without
parameters. Otherwise, the declaration:
included in main() would not have been valid.
Anyway, I have to warn you that an empty block is a bad implementation for a
constructor, since it does not fulfill the minimum functionality that is
generally expected from a constructor, which is the initialization of all the
member variables in its class. In our case this constructor leaves the variables
x and y undefined. Therefore, a more advisable definition would have been
something similar to this:
| CVector () { x=0; y=0; }; |
which in order to simplify and show only the point of the
code I have not included in the example.
As well as a class includes a default constructor and a copy constructor even if
they are not declared, it also includes a default definition for the assignment
operator (=) with the class itself as parameter. The behavior which is defined
by default is to copy the whole content of the data members of the object passed
as argument (the one at the right side of the sign) to the one at the left side:
CVector d (2,3);
CVector e;
e = d;
// copy assignment operator |
The copy assignment operator function is the only operator
member function implemented by default. Of course, you can redefine it to any
other functionality that you want, like for example, copy only certain class
members or perform additional initialization procedures.
The overload of operators does not force its operation to bear a relation to the
mathematical or usual meaning of the operator, although it is recommended. For
example, the code may not be very intuitive if you use operator + to subtract
two classes or operator== to fill with zeros a class, although it is perfectly
possible to do so.
Although the prototype of a function operator+ can seem obvious since it takes
what is at the right side of the operator as the parameter for the operator
member function of the object at its left side, other operators may not be so
obvious. Here you have a table with a summary on how the different operator
functions have to be declared (replace @ by the operator in each case):
| Expression |
Operator |
Member function |
Global function |
| @a |
+ - * & ! ~ ++ -- |
A::operator@() |
operator@(A) |
| a@ |
++ -- |
A::operator@(int) |
operator@(A,int) |
| a@b |
+ - * / % ^ & | < > == != <= >= << >> && || |
A::operator@ (B) |
operator@(A,B) |
| a@b |
= += -= *= /= %= ^= &= |= <<= >>= [] |
A::operator@ (B) |
- |
| a(b, c...) |
() |
A::operator() (B, C...) |
- |
| a->x |
-> |
A::operator->() |
- |
Where a is an object of class A, b is an object of class B
and c is an object of class C.
You can see in this panel that there are two ways to overload some class
operators: as a member function and as a global function. Its use is indistinct,
nevertheless I remind you that functions that are not members of a class cannot
access the private or protected members of that class unless the global function
is its friend (friendship is explained later).
NEXT >> The
Keyword this
Have a Question ?
post your questions here. It
will be answered as soon as possible.
Check
C Aptitude Questions
for more C Aptitude Interview Questions with Answers
Check
C Interview Questions
for more C Interview Questions with Answers.
|