SlideShare uma empresa Scribd logo
1 de 101
Operator overloading
Ilio Catallo - info@iliocatallo.it
Outline
• The complex type
• Mixed-mode arithme2c
• I/O operators
• Literals
• Bibliography
The complex type
Classes
We introduced classes as a tool for extending the set of concepts
we can reason about in our code
A class for complex numbers
Let us now assume that we need to perform some arithme2c on
complex numbers
A class for complex numbers
Since there is no built-in types modeling the concept of complex
numbers, we decide to introduce a new class1
1
In fairness, there already exists in the Standard Library the class std::complex
The complex type
class complex {
public:
complex(double re,
double im): re(re), im(im) {}
private:
double re;
double im;
};
The complex type
We can now define values of of type complex:
complex a(3, 5);
complex b(7, 1);
How can we make complex support addi2on?
Suppor&ng addi&on
It seems reasonable to add a member func*on named plus
class complex {
public:
... plus (...);
};
Suppor&ng addi&on
From mathema*cs, we know that adding two complex values x
and y results in a new complex value z
class complex {
public:
complex plus(...);
};
Suppor&ng addi&on
Moreover, adding two complex values x and y does not require
any change in either x or y
class complex {
public:
complex plus(complex const& y);
};
Suppor&ng addi&on
class complex {
public:
complex(double re,
double im): re(re), im(im) {}
complex plus(complex const& y) {
return complex(re + y.re,
im + y.im);
}
private:
double re;
double im;
};
Suppor&ng addi&on
We can now add together two complex values
complex a(3, 5);
complex b(7, 1);
complex c = a.plus(b);
Syntac'c noise
Although the above solu.on works, highly-nested expressions
might be difficult to parse due to syntac'c noise
a.plus(b.plus(c)).plus(d);
Syntac'c noise
Compare a.plus(b.plus(c)).plus(e) with the intended
expression:
(a + (b + c)) + d;
Why do we find (a + (b + c)) + d much more readable?
Conven&onal nota&on
This is because of our acquaintance with a conven&onal nota&on
Conven&onal nota&on
A"er all, such an expression is the result of hundreds of years of
experience with mathema/cal nota/on
(a + (b + c)) + d;
Operators on built-in types
This is why C++ supports a set of operators for its built-in types
float a = 2, b = 3,
c = 1, d = 10;
(a + (b + c)) + d;
Operators on UDTs
However, most concepts for which operators are conven3onally
used are not built-in types
Operators on UDTs
Just to name a few, the primary way of interac4ng with matrices
and complex numbers is through the use of operators on them
Operator overloading
Fortunately, C++ allows defining operators for user-defined types
complex a(3, 5);
complex b(7, 1);
complex c = a + b;
Operator overloading
We refer to such a prac.ce as operator overloading
complex a(3, 5);
complex b(7, 1);
complex c = a + b;
Operator overloading
Operator overloading allows operators to have user-defined
meanings on user-defined types
complex a(3, 5);
complex b(7, 1);
complex c = a + b;
Language of the problem domain
Users of our class can then program in the language of the problem
domain, rather than in the language of the machine
complex a(3, 5);
complex b(7, 1);
complex c = a + b; // a.plus(b);
Defining overloads
Each operator ~ can be overloaded by defining a corresponding
operator func,on named operator~
Defining operator+
Hence, we can overload operator + as follows:
class complex {
...
complex operator+(complex const& y);
};
Defining operator+
From an implementa-on viewpoint, operator+ does not differ
from our previous plus func-on
complex operator+(complex const& y) {
return complex(re + y.re,
im + y.im);
}
Operator func-ons
An operator func-on can be called like any other func-on2
complex c = a + b; // shorthand
complex c = a.operator+(b); // explicit call
2
However, note that only operators on user-defined types can be explicitly invoked. That is, we cannot do
int a = 3; int b = a.operator+(5);
The complex type
class complex {
public:
complex(double re,
double im): re(re), im(im) {}
complex operator+(complex const& y) {...}
private:
double re;
double im;
};
Mixed-mode arithme.c
Adding complexes and doubles
What happens when we try to do the following?
complex a(3, 5);
complex c = a + 2.3;
Adding complexes and doubles
We incur in a compile-)me error
complex a(3, 5);
// error: no match for 'operator+'
// (operand types are 'complex' and 'double')
complex c = a + 2.3;
Mixed-mode addi+on
We never defined addi+on between complex and double values
// error: no match for 'operator+'
complex c = a + 2.3;
An overload for doubles
We introduce an addi-onal overload for the specific case of right-
hand side operands of type double3
complex operator+(double const& y);
3
Here, we decided to use a pass-by-const-reference approach to stress the fact that addi7on is a non-muta7ng
opera7ons for both the operands. However, pass-by-value would have been an equally acceptable solu7on
An overload for doubles
We introduce an addi-onal overload for the specific case of right-
hand side operands of type double3
complex operator+(double const& y) {
return complex(re + y, im);
}
3
Here, we decided to use a pass-by-const-reference approach to stress the fact that addi7on is a non-muta7ng
opera7ons for both the operands. However, pass-by-value would have been an equally acceptable solu7on
An overload for doubles
Apparently, we can now perform mixed-mode arithme6c
complex a(3, 5);
complex c = a + 2.3; // it now compiles!
Commuta'vity of addi'on
However, users of our class expect addi4on to be commuta've
complex a(3, 5);
(a + 2.3) == (2.3 + a); // true!
Adding doubles and complexes
What happens if we do the following?
complex a(3, 5);
complex c = 2.3 + a;
Adding doubles and complexes
complex a(3, 5);
// error: no match for 'operator+'
// (operand types are 'double' and 'complex')
complex c = 2.3 + a;
Adding doubles and complexes
If double were a class, we could write a version of operator+
tailored for right-hand side operands of type complex
struct double {
...
complex operator+(complex const& y);
};
Non-member operator func0ons
Given that double is in fact a built-in type, we need an alterna4ve
way of defining addi4on with complex values
Non-member operator func0ons
For any binary operator ~, a~b can be interpreted as either
• a.operator~(b), or
• operator~(a, b)4
4
With the no*ceably excep*on, as we will see, of the assignment operator
Non-member operator func0ons
That is, a binary operator can be defined by either
• a member func*on taking one argument, or
• a non-member func1on taking two arguments
Adding doubles and complexes
The resul)ng non-member operator func)on is as follows:
complex operator+(double const& x, complex const& y);
Adding doubles and complexes
class complex {
public:
complex(double re,
double im): re(re), im(im) {}
complex operator+(complex const& y) {...}
complex operator+(double const& y) {...}
private:
double re;
double im;
};
complex operator+(double const& x, complex const& y);
Non-member operator func0ons
Intui&vely, we would like to write the following
complex operator+(double const& x, complex const& y) {
return complex(y.re + x, y.im);
}
Non-member operator func0ons
Since we are wri*ng a non-member func*on, we cannot directly
access the private members y.re and y.im
complex operator+(double const& x, complex const& y) {
return complex(y.re + x, y.im);
}
Non-member operator func0ons
Two solu(ons to this problem:
• Declare the non-member operator as a friend of the class
• Provide complex with access func9ons
Declaring func-ons as friends
The friend declara*on grants a func*on access to private
members of the class in which such a friend declara*on appears
Declaring operator+ as friend
class complex {
public:
complex(double re,
double im): re(re), im(im) {}
complex operator+(complex const& y) {...}
complex operator+(double const& y) {...}
friend
complex operator+(double const& x, complex const& y) {
return complex(y.re + x, y.im);
}
private:
double re;
double im;
};
Access func)ons
Alterna(vely, we can expose the data member re and im through
the so-called access func)ons (or, accessors)
Access func)ons
Alterna(vely, we can expose the data member re and im through
the so-called access func)ons (or, accessors)
Access func)ons
class complex {
public:
complex(double re,
double im): re(re), im(im) {}
complex operator+(complex const& y) {...}
complex operator+(double const& y) {...}
double real() { return re; } // access function
double imag() { return im; } // access function
private:
double re;
double im;
};
complex operator+(double const& x, complex const& y);
Non-member operator func0on
How to use our new access func.ons in order to implement
operator+?
complex operator+(double const& x, complex const& y);
Non-member operator func0on
How to use our new access func.ons in order to implement
operator+?
complex operator+(double const& x, complex const& y) {
return complex(x + y.real(), y.imag());
}
Non-member operator func0on
Unfortunately, our solu/on does not compile
// error: member function 'real' not viable:
// 'this' argument has type 'const complex',
// but function is not marked const
Const-correctness
Since we know that addi.on is a non-muta.ng opera.ons, we
correctly marked x and y as const
complex operator+(double const& x, complex const& y) {
return complex(x + y.real(), y.imag());
}
Const-correctness
However, we did not inform the compiler that the access func6ons
real() and imag() will not modify either y.re or y.im
Const-correctness
Hence, we cannot invoke either real() or imag() on a const
complex value
complex const a(3, 5);
std::cout << a.real(); // compile-time error!
std::cout << a.imag(); // compile-time error!
Const access func,ons
In order to do so, we mark as const both real() and imag()
class complex {
public:
...
double real() const { return re; }
double imag() const { return im; }
};
Constant operator func.ons
Moreover, we no*ce that we can do the same for the two member
variants of operator+
class complex {
public:
...
complex operator+(complex const& y) const {...}
complex operator+(double const& y) const {...}
};
Constant operator func.ons
This allows us to enforce that addi2on is a non-muta(ng
opera2ons for both the operands
class complex {
public:
...
complex operator+(complex const& y) const {...}
complex operator+(double const& y) const {...}
};
Const-correct complex type
class complex {
public:
complex(double re,
double im): re(re), im(im) {}
complex operator+(complex const& y) const {...}
complex operator+(double const& y) const {...}
double real() const { return re; }
double imag() const { return im; }
private:
double re;
double im;
};
complex operator+(double const& x, complex const& y) {
return complex(x + y.real(), y.imag());
}
Const-correctness
Const-correctness restricts users of our class to invoke on const
objects only those member func7ons that inspects, rather than
modify, member data
Mixed-mode arithme.c
We now finally support mixed-mode arithme6c for addi6on
complex a(3, 5);
(a + 2.3) == (2.3 + a); // true!
Equality
But...what happens if we actually try this code?
complex a(3, 5);
(a + 2.3) == (2.3 + a);
Equality
We get yet another compile-)me error
complex a(3, 5);
// error: invalid operands to binary expression
// ('complex' and 'complex')
(a + 2.3) == (2.3 + a);
Equality
This is because we never defined equality between complex
values
complex a(3, 5);
a == a;
Overloading operator==
To this end, we need to overload operator == for complex values
Overloading operator==
Specifically, we opt for the non-member version of operator== in
order to enforce the symmetry of equality
bool operator==(complex const& x, complex const& y);
Overloading operator==
Fortunately, the implementa1on of operator== is straigh5orward
bool operator==(complex const& x, complex const& y) {
return x.real() == y.real() &&
x.imag() == y.imag();
}
Inequality
Moreover, users typically expect inequality to be defined whenever
equality is
complex a(3, 5);
complex b(7, 1);
a != b; // true!
Inequality
Therefore, it is not sufficient to overload equality. We must
overload inequality as well
bool operator!=(complex const& x, complex const& y);
Inequality
Therefore, it is not sufficient to overload equality. We must
overload inequality as well
bool operator!=(complex const& x, complex const& y) {
return !(x == y);
}
The complex type
class complex {
public:
complex(double re,
double im): re(re), im(im) {}
complex operator+(complex const& y) const {...}
complex operator+(double const& y) const {...}
double real() const { return re; }
double imag() const { return im; }
private:
double re;
double im;
};
complex operator+(double const& x, complex const& y) {...}
bool operator==(complex const& x, complex const& y) {...}
bool operator!=(complex const& x, complex const& y) {...}
Group of opera*ons
The same can be said for other related opera3ons such as:
• +, +=, -, -=, etc.
• >, <, >=, <=
Group of opera*ons
Therefore, it is fundamental to define related opera2ons together
I/O operators
I/O operators
Besides the I/O of built-in types and std::strings, iostream
allows programmers to define I/O for their own types
complex a(3, 5);
std::cout << a;
I/O operators
I/O on user-defined types is possible by overloading, respec9vely,
operator<< and operator>>
Output operator
Let us focus on the output operator operator<<
complex a(3, 5);
std::cout << a;
Output operator
We know that std::cout << a can be intended as
operator<<(std::cout, a);
Non-member output operator
Since our type appears as the right-hand side operands, we need
to specify a non-member operator func4on
void operator<<(..., complex const& x);
Non-member output operator
Given that std::cout is a global object of type std::ostream,
and that outpu2ng is a muta-ng opera5on, we obtain
void operator<<(std::ostream& os, complex const& x);
Non-member output operator
Apparently, the following suffices
void operator<<(std::ostream& os, complex const& x) {
os << x.real() << " + "
<< x.imag() << "i";
}
Chaining
However, our implementa1on of operator<< does not support
chaining
complex a(3, 5);
std::cout << a << " is our magic number";
Chaining
We need std::cout << a to evaluate to std::cout
std::ostream& operator<<(std::ostream& os,
complex const& x);
Chaining
In other words, operator<< must return std::cout
std::ostream& operator<<(std::ostream& os,
complex const& x);
Chaining
In other words, operator<< must return std::cout
std::ostream& operator<<(std::ostream& os, complex const& x) {
os << x.real() << " + "
<< x.imag() << "i";
return os;
}
Literals
Literals
C++ provides literals for a variety of types
char c = 'a';
float f = 1.2f;
int i = 123;
User-defined literals
In addi'on, with C++11 and above we can define literals for user-
defined types
// 3.5i is a user-defined literal
complex a = 3.5i;
Literal operators
Such user-defined literals are supported through the no4on of
literal operators
complex a = 3.5i;
Literal operators
Literal operators map literals with a given suffix into a desired type
3.5i → complex(0, 3.5)
Literal operators
The literal operator is a non-member func4on named operator""
followed by the suffix5
complex operator"" i(long double x) {
return complex(0, x);
}
5
Note that, C++14 introduced the i literal suffix to match the std::complex type. Therefore, in real code we
should not overload it manually
Language of the problem domain
We can now write
complex a = 7.1 + 3.5i;
std::cout << a;
Language of the problem domain
For the case of complex values, our new user-defined literal helps
us ge8ng even closer to the language of the problem domain
complex a = 7.1 + 3.5i;
std::cout << a;
Bibliography
Bibliography
• B. Stroustrup, The C++ Programming Language (4th
ed.)
• B, Stroustrup, Programming: Principles and Prac@ce
Using C++ (2nd
ed.)
• C++ Reference, Operator overloading
• ISO C++, C++ FAQ

Mais conteúdo relacionado

Mais procurados

Operator overloading
Operator overloadingOperator overloading
Operator overloading
Kumar
 
Operator Overloading & Type Conversions
Operator Overloading & Type ConversionsOperator Overloading & Type Conversions
Operator Overloading & Type Conversions
Rokonuzzaman Rony
 
Operator overloading
Operator overloadingOperator overloading
Operator overloading
abhay singh
 
Operator overloadng
Operator overloadngOperator overloadng
Operator overloadng
preethalal
 
C++: inheritance, composition, polymorphism
C++: inheritance, composition, polymorphismC++: inheritance, composition, polymorphism
C++: inheritance, composition, polymorphism
Jussi Pohjolainen
 
Operator overloading
Operator overloadingOperator overloading
Operator overloading
Kamal Acharya
 

Mais procurados (20)

Operator overloading in C++
Operator  overloading in C++Operator  overloading in C++
Operator overloading in C++
 
c++
c++c++
c++
 
Operator overloading
Operator overloadingOperator overloading
Operator overloading
 
Operator overloading
Operator overloadingOperator overloading
Operator overloading
 
Operator overloading
Operator overloadingOperator overloading
Operator overloading
 
Operator overloading
Operator overloadingOperator overloading
Operator overloading
 
Operator overloading
Operator overloadingOperator overloading
Operator overloading
 
Operator overloading
Operator overloadingOperator overloading
Operator overloading
 
Operator overloading
Operator overloadingOperator overloading
Operator overloading
 
Operator Overloading & Type Conversions
Operator Overloading & Type ConversionsOperator Overloading & Type Conversions
Operator Overloading & Type Conversions
 
OPERATOR OVERLOADING IN C++
OPERATOR OVERLOADING IN C++OPERATOR OVERLOADING IN C++
OPERATOR OVERLOADING IN C++
 
Operator overloading
Operator overloadingOperator overloading
Operator overloading
 
Operator overloadng
Operator overloadngOperator overloadng
Operator overloadng
 
Overloading
OverloadingOverloading
Overloading
 
operator overloading
operator overloadingoperator overloading
operator overloading
 
Bca 2nd sem u-4 operator overloading
Bca 2nd sem u-4 operator overloadingBca 2nd sem u-4 operator overloading
Bca 2nd sem u-4 operator overloading
 
C++ overloading
C++ overloadingC++ overloading
C++ overloading
 
operator overloading & type conversion in cpp over view || c++
operator overloading & type conversion in cpp over view || c++operator overloading & type conversion in cpp over view || c++
operator overloading & type conversion in cpp over view || c++
 
C++: inheritance, composition, polymorphism
C++: inheritance, composition, polymorphismC++: inheritance, composition, polymorphism
C++: inheritance, composition, polymorphism
 
Operator overloading
Operator overloadingOperator overloading
Operator overloading
 

Destaque

08 c++ Operator Overloading.ppt
08 c++ Operator Overloading.ppt08 c++ Operator Overloading.ppt
08 c++ Operator Overloading.ppt
Tareq Hasan
 
Presentation on overloading
Presentation on overloading Presentation on overloading
Presentation on overloading
Charndeep Sekhon
 
Lec 26.27-operator overloading
Lec 26.27-operator overloadingLec 26.27-operator overloading
Lec 26.27-operator overloading
Princess Sam
 

Destaque (18)

08 c++ Operator Overloading.ppt
08 c++ Operator Overloading.ppt08 c++ Operator Overloading.ppt
08 c++ Operator Overloading.ppt
 
operator overloading in c++
operator overloading in c++operator overloading in c++
operator overloading in c++
 
Presentation on overloading
Presentation on overloading Presentation on overloading
Presentation on overloading
 
Function overloading
Function overloadingFunction overloading
Function overloading
 
Arrays in C++
Arrays in C++Arrays in C++
Arrays in C++
 
Resource wrappers in C++
Resource wrappers in C++Resource wrappers in C++
Resource wrappers in C++
 
Operator Overloading and Scope of Variable
Operator Overloading and Scope of VariableOperator Overloading and Scope of Variable
Operator Overloading and Scope of Variable
 
Operator Overloading
Operator OverloadingOperator Overloading
Operator Overloading
 
Regular types in C++
Regular types in C++Regular types in C++
Regular types in C++
 
Lec 26.27-operator overloading
Lec 26.27-operator overloadingLec 26.27-operator overloading
Lec 26.27-operator overloading
 
inheritance c++
inheritance c++inheritance c++
inheritance c++
 
C++ Standard Template Library
C++ Standard Template LibraryC++ Standard Template Library
C++ Standard Template Library
 
Inheritance in C++
Inheritance in C++Inheritance in C++
Inheritance in C++
 
Operator overloading and type conversions
Operator overloading and type conversionsOperator overloading and type conversions
Operator overloading and type conversions
 
Function overloading(c++)
Function overloading(c++)Function overloading(c++)
Function overloading(c++)
 
Function Overlaoding
Function OverlaodingFunction Overlaoding
Function Overlaoding
 
06. operator overloading
06. operator overloading06. operator overloading
06. operator overloading
 
Function overloading
Function overloadingFunction overloading
Function overloading
 

Semelhante a Operator overloading in C++

Chapter24 operator-overloading
Chapter24 operator-overloadingChapter24 operator-overloading
Chapter24 operator-overloading
Deepak Singh
 
C++ Function
C++ FunctionC++ Function
C++ Function
Hajar
 
08 c-operator-overloadingppt2563
08 c-operator-overloadingppt256308 c-operator-overloadingppt2563
08 c-operator-overloadingppt2563
Youth For Peace
 
Operator oveerloading
Operator oveerloadingOperator oveerloading
Operator oveerloading
yatinnarula
 
Lec 28 - operator overloading
Lec 28 - operator overloadingLec 28 - operator overloading
Lec 28 - operator overloading
Princess Sam
 

Semelhante a Operator overloading in C++ (20)

Ch-4-Operator Overloading.pdf
Ch-4-Operator Overloading.pdfCh-4-Operator Overloading.pdf
Ch-4-Operator Overloading.pdf
 
Operator overloading2
Operator overloading2Operator overloading2
Operator overloading2
 
Chapter24 operator-overloading
Chapter24 operator-overloadingChapter24 operator-overloading
Chapter24 operator-overloading
 
3d7b7 session4 c++
3d7b7 session4 c++3d7b7 session4 c++
3d7b7 session4 c++
 
overloading in C++
overloading in C++overloading in C++
overloading in C++
 
Unary operator overloading
Unary operator overloadingUnary operator overloading
Unary operator overloading
 
C++ Function
C++ FunctionC++ Function
C++ Function
 
Oops
OopsOops
Oops
 
Functional Programming in JavaScript
Functional Programming in JavaScriptFunctional Programming in JavaScript
Functional Programming in JavaScript
 
CppOperators.ppt
CppOperators.pptCppOperators.ppt
CppOperators.ppt
 
Week7a.pptx
Week7a.pptxWeek7a.pptx
Week7a.pptx
 
Binary operator overloading
Binary operator overloadingBinary operator overloading
Binary operator overloading
 
ForLoopandUserDefinedFunctions.pptx
ForLoopandUserDefinedFunctions.pptxForLoopandUserDefinedFunctions.pptx
ForLoopandUserDefinedFunctions.pptx
 
08 c-operator-overloadingppt2563
08 c-operator-overloadingppt256308 c-operator-overloadingppt2563
08 c-operator-overloadingppt2563
 
Operator oveerloading
Operator oveerloadingOperator oveerloading
Operator oveerloading
 
M11 operator overloading and type conversion
M11 operator overloading and type conversionM11 operator overloading and type conversion
M11 operator overloading and type conversion
 
3. Polymorphism.pptx
3. Polymorphism.pptx3. Polymorphism.pptx
3. Polymorphism.pptx
 
Bc0037
Bc0037Bc0037
Bc0037
 
Lec 28 - operator overloading
Lec 28 - operator overloadingLec 28 - operator overloading
Lec 28 - operator overloading
 
Lecture5
Lecture5Lecture5
Lecture5
 

Mais de Ilio Catallo

Community Detection
Community DetectionCommunity Detection
Community Detection
Ilio Catallo
 
WWW12 - The CUbRIK Project
WWW12 - The CUbRIK ProjectWWW12 - The CUbRIK Project
WWW12 - The CUbRIK Project
Ilio Catallo
 

Mais de Ilio Catallo (19)

Memory management in C++
Memory management in C++Memory management in C++
Memory management in C++
 
Multidimensional arrays in C++
Multidimensional arrays in C++Multidimensional arrays in C++
Multidimensional arrays in C++
 
Pointers & References in C++
Pointers & References in C++Pointers & References in C++
Pointers & References in C++
 
Spring MVC - Wiring the different layers
Spring MVC -  Wiring the different layersSpring MVC -  Wiring the different layers
Spring MVC - Wiring the different layers
 
Java and Java platforms
Java and Java platformsJava and Java platforms
Java and Java platforms
 
Spring MVC - Web Forms
Spring MVC  - Web FormsSpring MVC  - Web Forms
Spring MVC - Web Forms
 
Spring MVC - The Basics
Spring MVC -  The BasicsSpring MVC -  The Basics
Spring MVC - The Basics
 
Web application architecture
Web application architectureWeb application architecture
Web application architecture
 
Introduction To Spring
Introduction To SpringIntroduction To Spring
Introduction To Spring
 
Gestione della memoria in C++
Gestione della memoria in C++Gestione della memoria in C++
Gestione della memoria in C++
 
Array in C++
Array in C++Array in C++
Array in C++
 
Puntatori e Riferimenti
Puntatori e RiferimentiPuntatori e Riferimenti
Puntatori e Riferimenti
 
Java Persistence API
Java Persistence APIJava Persistence API
Java Persistence API
 
JSP Standard Tag Library
JSP Standard Tag LibraryJSP Standard Tag Library
JSP Standard Tag Library
 
Internationalization in Jakarta Struts 1.3
Internationalization in Jakarta Struts 1.3Internationalization in Jakarta Struts 1.3
Internationalization in Jakarta Struts 1.3
 
Validation in Jakarta Struts 1.3
Validation in Jakarta Struts 1.3Validation in Jakarta Struts 1.3
Validation in Jakarta Struts 1.3
 
Introduction to Struts 1.3
Introduction to Struts 1.3Introduction to Struts 1.3
Introduction to Struts 1.3
 
Community Detection
Community DetectionCommunity Detection
Community Detection
 
WWW12 - The CUbRIK Project
WWW12 - The CUbRIK ProjectWWW12 - The CUbRIK Project
WWW12 - The CUbRIK Project
 

Último

Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Victor Rentea
 

Último (20)

Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
 
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
 
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingRepurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
 
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWEREMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
 
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
 
Platformless Horizons for Digital Adaptability
Platformless Horizons for Digital AdaptabilityPlatformless Horizons for Digital Adaptability
Platformless Horizons for Digital Adaptability
 
WSO2's API Vision: Unifying Control, Empowering Developers
WSO2's API Vision: Unifying Control, Empowering DevelopersWSO2's API Vision: Unifying Control, Empowering Developers
WSO2's API Vision: Unifying Control, Empowering Developers
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
AWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of Terraform
 
AI+A11Y 11MAY2024 HYDERBAD GAAD 2024 - HelloA11Y (11 May 2024)
AI+A11Y 11MAY2024 HYDERBAD GAAD 2024 - HelloA11Y (11 May 2024)AI+A11Y 11MAY2024 HYDERBAD GAAD 2024 - HelloA11Y (11 May 2024)
AI+A11Y 11MAY2024 HYDERBAD GAAD 2024 - HelloA11Y (11 May 2024)
 
JohnPollard-hybrid-app-RailsConf2024.pptx
JohnPollard-hybrid-app-RailsConf2024.pptxJohnPollard-hybrid-app-RailsConf2024.pptx
JohnPollard-hybrid-app-RailsConf2024.pptx
 
Artificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : UncertaintyArtificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : Uncertainty
 
DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 AmsterdamDEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
 
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ..."I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
 
Spring Boot vs Quarkus the ultimate battle - DevoxxUK
Spring Boot vs Quarkus the ultimate battle - DevoxxUKSpring Boot vs Quarkus the ultimate battle - DevoxxUK
Spring Boot vs Quarkus the ultimate battle - DevoxxUK
 
Exploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with MilvusExploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with Milvus
 
presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century education
 
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
 
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
 

Operator overloading in C++

  • 1. Operator overloading Ilio Catallo - info@iliocatallo.it
  • 2. Outline • The complex type • Mixed-mode arithme2c • I/O operators • Literals • Bibliography
  • 4. Classes We introduced classes as a tool for extending the set of concepts we can reason about in our code
  • 5. A class for complex numbers Let us now assume that we need to perform some arithme2c on complex numbers
  • 6. A class for complex numbers Since there is no built-in types modeling the concept of complex numbers, we decide to introduce a new class1 1 In fairness, there already exists in the Standard Library the class std::complex
  • 7. The complex type class complex { public: complex(double re, double im): re(re), im(im) {} private: double re; double im; };
  • 8. The complex type We can now define values of of type complex: complex a(3, 5); complex b(7, 1);
  • 9. How can we make complex support addi2on?
  • 10. Suppor&ng addi&on It seems reasonable to add a member func*on named plus class complex { public: ... plus (...); };
  • 11. Suppor&ng addi&on From mathema*cs, we know that adding two complex values x and y results in a new complex value z class complex { public: complex plus(...); };
  • 12. Suppor&ng addi&on Moreover, adding two complex values x and y does not require any change in either x or y class complex { public: complex plus(complex const& y); };
  • 13. Suppor&ng addi&on class complex { public: complex(double re, double im): re(re), im(im) {} complex plus(complex const& y) { return complex(re + y.re, im + y.im); } private: double re; double im; };
  • 14. Suppor&ng addi&on We can now add together two complex values complex a(3, 5); complex b(7, 1); complex c = a.plus(b);
  • 15. Syntac'c noise Although the above solu.on works, highly-nested expressions might be difficult to parse due to syntac'c noise a.plus(b.plus(c)).plus(d);
  • 16. Syntac'c noise Compare a.plus(b.plus(c)).plus(e) with the intended expression: (a + (b + c)) + d;
  • 17. Why do we find (a + (b + c)) + d much more readable?
  • 18. Conven&onal nota&on This is because of our acquaintance with a conven&onal nota&on
  • 19. Conven&onal nota&on A"er all, such an expression is the result of hundreds of years of experience with mathema/cal nota/on (a + (b + c)) + d;
  • 20. Operators on built-in types This is why C++ supports a set of operators for its built-in types float a = 2, b = 3, c = 1, d = 10; (a + (b + c)) + d;
  • 21. Operators on UDTs However, most concepts for which operators are conven3onally used are not built-in types
  • 22. Operators on UDTs Just to name a few, the primary way of interac4ng with matrices and complex numbers is through the use of operators on them
  • 23. Operator overloading Fortunately, C++ allows defining operators for user-defined types complex a(3, 5); complex b(7, 1); complex c = a + b;
  • 24. Operator overloading We refer to such a prac.ce as operator overloading complex a(3, 5); complex b(7, 1); complex c = a + b;
  • 25. Operator overloading Operator overloading allows operators to have user-defined meanings on user-defined types complex a(3, 5); complex b(7, 1); complex c = a + b;
  • 26. Language of the problem domain Users of our class can then program in the language of the problem domain, rather than in the language of the machine complex a(3, 5); complex b(7, 1); complex c = a + b; // a.plus(b);
  • 27. Defining overloads Each operator ~ can be overloaded by defining a corresponding operator func,on named operator~
  • 28. Defining operator+ Hence, we can overload operator + as follows: class complex { ... complex operator+(complex const& y); };
  • 29. Defining operator+ From an implementa-on viewpoint, operator+ does not differ from our previous plus func-on complex operator+(complex const& y) { return complex(re + y.re, im + y.im); }
  • 30. Operator func-ons An operator func-on can be called like any other func-on2 complex c = a + b; // shorthand complex c = a.operator+(b); // explicit call 2 However, note that only operators on user-defined types can be explicitly invoked. That is, we cannot do int a = 3; int b = a.operator+(5);
  • 31. The complex type class complex { public: complex(double re, double im): re(re), im(im) {} complex operator+(complex const& y) {...} private: double re; double im; };
  • 33. Adding complexes and doubles What happens when we try to do the following? complex a(3, 5); complex c = a + 2.3;
  • 34. Adding complexes and doubles We incur in a compile-)me error complex a(3, 5); // error: no match for 'operator+' // (operand types are 'complex' and 'double') complex c = a + 2.3;
  • 35. Mixed-mode addi+on We never defined addi+on between complex and double values // error: no match for 'operator+' complex c = a + 2.3;
  • 36. An overload for doubles We introduce an addi-onal overload for the specific case of right- hand side operands of type double3 complex operator+(double const& y); 3 Here, we decided to use a pass-by-const-reference approach to stress the fact that addi7on is a non-muta7ng opera7ons for both the operands. However, pass-by-value would have been an equally acceptable solu7on
  • 37. An overload for doubles We introduce an addi-onal overload for the specific case of right- hand side operands of type double3 complex operator+(double const& y) { return complex(re + y, im); } 3 Here, we decided to use a pass-by-const-reference approach to stress the fact that addi7on is a non-muta7ng opera7ons for both the operands. However, pass-by-value would have been an equally acceptable solu7on
  • 38. An overload for doubles Apparently, we can now perform mixed-mode arithme6c complex a(3, 5); complex c = a + 2.3; // it now compiles!
  • 39. Commuta'vity of addi'on However, users of our class expect addi4on to be commuta've complex a(3, 5); (a + 2.3) == (2.3 + a); // true!
  • 40. Adding doubles and complexes What happens if we do the following? complex a(3, 5); complex c = 2.3 + a;
  • 41. Adding doubles and complexes complex a(3, 5); // error: no match for 'operator+' // (operand types are 'double' and 'complex') complex c = 2.3 + a;
  • 42. Adding doubles and complexes If double were a class, we could write a version of operator+ tailored for right-hand side operands of type complex struct double { ... complex operator+(complex const& y); };
  • 43. Non-member operator func0ons Given that double is in fact a built-in type, we need an alterna4ve way of defining addi4on with complex values
  • 44. Non-member operator func0ons For any binary operator ~, a~b can be interpreted as either • a.operator~(b), or • operator~(a, b)4 4 With the no*ceably excep*on, as we will see, of the assignment operator
  • 45. Non-member operator func0ons That is, a binary operator can be defined by either • a member func*on taking one argument, or • a non-member func1on taking two arguments
  • 46. Adding doubles and complexes The resul)ng non-member operator func)on is as follows: complex operator+(double const& x, complex const& y);
  • 47. Adding doubles and complexes class complex { public: complex(double re, double im): re(re), im(im) {} complex operator+(complex const& y) {...} complex operator+(double const& y) {...} private: double re; double im; }; complex operator+(double const& x, complex const& y);
  • 48. Non-member operator func0ons Intui&vely, we would like to write the following complex operator+(double const& x, complex const& y) { return complex(y.re + x, y.im); }
  • 49. Non-member operator func0ons Since we are wri*ng a non-member func*on, we cannot directly access the private members y.re and y.im complex operator+(double const& x, complex const& y) { return complex(y.re + x, y.im); }
  • 50. Non-member operator func0ons Two solu(ons to this problem: • Declare the non-member operator as a friend of the class • Provide complex with access func9ons
  • 51. Declaring func-ons as friends The friend declara*on grants a func*on access to private members of the class in which such a friend declara*on appears
  • 52. Declaring operator+ as friend class complex { public: complex(double re, double im): re(re), im(im) {} complex operator+(complex const& y) {...} complex operator+(double const& y) {...} friend complex operator+(double const& x, complex const& y) { return complex(y.re + x, y.im); } private: double re; double im; };
  • 53. Access func)ons Alterna(vely, we can expose the data member re and im through the so-called access func)ons (or, accessors)
  • 54. Access func)ons Alterna(vely, we can expose the data member re and im through the so-called access func)ons (or, accessors)
  • 55. Access func)ons class complex { public: complex(double re, double im): re(re), im(im) {} complex operator+(complex const& y) {...} complex operator+(double const& y) {...} double real() { return re; } // access function double imag() { return im; } // access function private: double re; double im; }; complex operator+(double const& x, complex const& y);
  • 56. Non-member operator func0on How to use our new access func.ons in order to implement operator+? complex operator+(double const& x, complex const& y);
  • 57. Non-member operator func0on How to use our new access func.ons in order to implement operator+? complex operator+(double const& x, complex const& y) { return complex(x + y.real(), y.imag()); }
  • 58. Non-member operator func0on Unfortunately, our solu/on does not compile // error: member function 'real' not viable: // 'this' argument has type 'const complex', // but function is not marked const
  • 59. Const-correctness Since we know that addi.on is a non-muta.ng opera.ons, we correctly marked x and y as const complex operator+(double const& x, complex const& y) { return complex(x + y.real(), y.imag()); }
  • 60. Const-correctness However, we did not inform the compiler that the access func6ons real() and imag() will not modify either y.re or y.im
  • 61. Const-correctness Hence, we cannot invoke either real() or imag() on a const complex value complex const a(3, 5); std::cout << a.real(); // compile-time error! std::cout << a.imag(); // compile-time error!
  • 62. Const access func,ons In order to do so, we mark as const both real() and imag() class complex { public: ... double real() const { return re; } double imag() const { return im; } };
  • 63. Constant operator func.ons Moreover, we no*ce that we can do the same for the two member variants of operator+ class complex { public: ... complex operator+(complex const& y) const {...} complex operator+(double const& y) const {...} };
  • 64. Constant operator func.ons This allows us to enforce that addi2on is a non-muta(ng opera2ons for both the operands class complex { public: ... complex operator+(complex const& y) const {...} complex operator+(double const& y) const {...} };
  • 65. Const-correct complex type class complex { public: complex(double re, double im): re(re), im(im) {} complex operator+(complex const& y) const {...} complex operator+(double const& y) const {...} double real() const { return re; } double imag() const { return im; } private: double re; double im; }; complex operator+(double const& x, complex const& y) { return complex(x + y.real(), y.imag()); }
  • 66. Const-correctness Const-correctness restricts users of our class to invoke on const objects only those member func7ons that inspects, rather than modify, member data
  • 67. Mixed-mode arithme.c We now finally support mixed-mode arithme6c for addi6on complex a(3, 5); (a + 2.3) == (2.3 + a); // true!
  • 68. Equality But...what happens if we actually try this code? complex a(3, 5); (a + 2.3) == (2.3 + a);
  • 69. Equality We get yet another compile-)me error complex a(3, 5); // error: invalid operands to binary expression // ('complex' and 'complex') (a + 2.3) == (2.3 + a);
  • 70. Equality This is because we never defined equality between complex values complex a(3, 5); a == a;
  • 71. Overloading operator== To this end, we need to overload operator == for complex values
  • 72. Overloading operator== Specifically, we opt for the non-member version of operator== in order to enforce the symmetry of equality bool operator==(complex const& x, complex const& y);
  • 73. Overloading operator== Fortunately, the implementa1on of operator== is straigh5orward bool operator==(complex const& x, complex const& y) { return x.real() == y.real() && x.imag() == y.imag(); }
  • 74. Inequality Moreover, users typically expect inequality to be defined whenever equality is complex a(3, 5); complex b(7, 1); a != b; // true!
  • 75. Inequality Therefore, it is not sufficient to overload equality. We must overload inequality as well bool operator!=(complex const& x, complex const& y);
  • 76. Inequality Therefore, it is not sufficient to overload equality. We must overload inequality as well bool operator!=(complex const& x, complex const& y) { return !(x == y); }
  • 77. The complex type class complex { public: complex(double re, double im): re(re), im(im) {} complex operator+(complex const& y) const {...} complex operator+(double const& y) const {...} double real() const { return re; } double imag() const { return im; } private: double re; double im; }; complex operator+(double const& x, complex const& y) {...} bool operator==(complex const& x, complex const& y) {...} bool operator!=(complex const& x, complex const& y) {...}
  • 78. Group of opera*ons The same can be said for other related opera3ons such as: • +, +=, -, -=, etc. • >, <, >=, <=
  • 79. Group of opera*ons Therefore, it is fundamental to define related opera2ons together
  • 81. I/O operators Besides the I/O of built-in types and std::strings, iostream allows programmers to define I/O for their own types complex a(3, 5); std::cout << a;
  • 82. I/O operators I/O on user-defined types is possible by overloading, respec9vely, operator<< and operator>>
  • 83. Output operator Let us focus on the output operator operator<< complex a(3, 5); std::cout << a;
  • 84. Output operator We know that std::cout << a can be intended as operator<<(std::cout, a);
  • 85. Non-member output operator Since our type appears as the right-hand side operands, we need to specify a non-member operator func4on void operator<<(..., complex const& x);
  • 86. Non-member output operator Given that std::cout is a global object of type std::ostream, and that outpu2ng is a muta-ng opera5on, we obtain void operator<<(std::ostream& os, complex const& x);
  • 87. Non-member output operator Apparently, the following suffices void operator<<(std::ostream& os, complex const& x) { os << x.real() << " + " << x.imag() << "i"; }
  • 88. Chaining However, our implementa1on of operator<< does not support chaining complex a(3, 5); std::cout << a << " is our magic number";
  • 89. Chaining We need std::cout << a to evaluate to std::cout std::ostream& operator<<(std::ostream& os, complex const& x);
  • 90. Chaining In other words, operator<< must return std::cout std::ostream& operator<<(std::ostream& os, complex const& x);
  • 91. Chaining In other words, operator<< must return std::cout std::ostream& operator<<(std::ostream& os, complex const& x) { os << x.real() << " + " << x.imag() << "i"; return os; }
  • 93. Literals C++ provides literals for a variety of types char c = 'a'; float f = 1.2f; int i = 123;
  • 94. User-defined literals In addi'on, with C++11 and above we can define literals for user- defined types // 3.5i is a user-defined literal complex a = 3.5i;
  • 95. Literal operators Such user-defined literals are supported through the no4on of literal operators complex a = 3.5i;
  • 96. Literal operators Literal operators map literals with a given suffix into a desired type 3.5i → complex(0, 3.5)
  • 97. Literal operators The literal operator is a non-member func4on named operator"" followed by the suffix5 complex operator"" i(long double x) { return complex(0, x); } 5 Note that, C++14 introduced the i literal suffix to match the std::complex type. Therefore, in real code we should not overload it manually
  • 98. Language of the problem domain We can now write complex a = 7.1 + 3.5i; std::cout << a;
  • 99. Language of the problem domain For the case of complex values, our new user-defined literal helps us ge8ng even closer to the language of the problem domain complex a = 7.1 + 3.5i; std::cout << a;
  • 101. Bibliography • B. Stroustrup, The C++ Programming Language (4th ed.) • B, Stroustrup, Programming: Principles and Prac@ce Using C++ (2nd ed.) • C++ Reference, Operator overloading • ISO C++, C++ FAQ