PE 2023 CPP Lecture 05
PE 2023 CPP Lecture 05
Groth
2023-07-06
Outline
Friend functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
Copy constructor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
The this pointer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
Operator overloading . . . . . . . . . . . . . . . . . . . . . . . . . . 20
Namespaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
Templates . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
Standard Template Library . . . . . . . . . . . . . . . . . . . . . . . . 59
Exercise C++ Templates . . . . . . . . . . . . . . . . . . . . . . . . 92
ñ If we don’t do this then, we have a memory leak! Memory for those pointers
is not released if an objects is destroyed.
class String {
private:
char *s;
int size;
public:
String(const char *str = NULL); // constructor
~String() { delete [] s; }// destructor
void print() { cout << s << endl; }
void change(const char *);
};
int main() {
String str1("GeeksQuiz");
String str2 = str1;
class Box {
public:
// Constructor definition
Box(double l = 2.0, double b = 2.0,
double h = 2.0) {
cout <<"Constructor called." << endl;
length = l;
breadth = b;
height = h;
}
double Volume() {
Groth / PE 2023 / Templates / Lecture 16/96
return length * breadth * height;
}
int compare(Box box) {
return this->Volume() > box.Volume();
}
int compare2(Box box) {
return Volume() > box.Volume();
}
private:
double length; // Length of a box
double breadth; // Breadth of a box
double height; // Height of a box
};
int main(void) {
Box Box1(3.3, 1.2, 1.5); // Declare box1
declares the addition operator that can be used to add two Box
objects and returns final Box object. Most overloaded operators
may be defined as ordinary non-member functions or as class
member functions.
class Box {
public:
double getVolume(void) {
return length * breadth * height;
}
void setLength( double len ) {
length = len;
}
void setBreadth( double bre ) {
breadth = bre;
}
void setHeight( double hei ) {
Groth / PE 2023 / Templates / Lecture 23/96
height = hei;
}
private:
double length; // Length of a box
double breadth; // Breadth of a box
double height; // Height of a box
// box 1 specification
Box1.setLength(6.0);
Box1.setBreadth(7.0);
Box1.setHeight(5.0);
// box 2 specification
Box2.setLength(12.0);
// volume of box 1
volume = Box1.getVolume();
cout << "Volume of Box1 : " << volume <<endl;
// volume of box 2
volume = Box2.getVolume();
cout << "Volume of Box2 : " << volume <<endl;
// volume of box 3
volume = Box3.getVolume();
return 0;
}
$ g++ -o opoverload.cpp.bin -std=c++17 -fconcepts opoverload.cpp &&
./opoverload.cpp.bin
Volume of Box1 : 210
Volume of Box2 : 1560
Volume of Box3 : 5400
a = b * c;
That seems innocent enough, doesn’t it? Well, many are quick to point out
that in C++ that could mean anything, rather than simple multiplication. You
see, you can overload the operator to change it’s meaning. In fact you can even
change what that equal sign means. What at first glance appears to be a
simple multiply and assign could in fact be absolutely anything!
I’ll gladly admit that you could do that in C++, but you probably wouldn’t. In
fact if you completely changed the meaning of common operators you’re likely
an idiot. But I don’t think a language should limit its features just to prevent
fools from misusing them. That simply isn’t possible, some fool will always
come around and mess it up. Consider the languages that allow overriding of
functions, but not operators. We can rewrite the above as below.
Groth / PE 2023 / Templates / Lecture 28/96
a.assign( b.mul( c ) );
Though perhaps not quite as clear as the first bit of code, nobody would really
doubt what that code was supposed to be doing. But what if mul wasn’t
actually multiplying, and what if assign wasn’t actually assigning a value. What
those functions do is totally at the whim of the programmer. In fact, now that I
look at it, this doesn’t even have anything to do with overloading. An idiot
could write misleading code in any language with very little effort.
[https://mortoray.com — Evil and Joy of overloading, 2010]
ñ As with anything: too much is too much, but used with care and at the
right place operator overloading can be powerful!!
ñ Why should a PL disallow us nice things because they can be possibly
misused??
ñ We use knives, do we??
return 0;
}
$ g++ -o nsp.cpp.bin -std=c++17 -fconcepts nsp.cpp && ./nsp.cpp.bin
Inside first_space
Inside second_space
#include <iostream>
using namespace std;
namespace first_space { // first name space
void func() {
cout << "Inside first_space" << endl;
}
Inside first_space
ñ No use of “using” in header files!
return 0;
}
$ g++ -o nested.cpp.bin -std=c++17 -fconcepts nested.cpp &&
./nested.cpp.bin
Inside second_space
Syntax
namespace alias_name = ns_name; (1)
namespace alias_name = ::ns_name; (2)
namespace alias_name = nested_name::ns_name; (3)
int main () {
int i = 39;
int j = 20;
cout << "Max(i, j): " << Max(i, j) << endl;
Groth / PE 2023 / Templates / Lecture 45/96
double f1 = 13.5;
double f2 = 20.7;
cout << "Max(f1, f2): " << Max(f1, f2) << endl;
string s1 = "Hello";
string s2 = "World";
cout << "Max(s1, s2): " << Max(s1, s2) << endl;
return 0;
}
$ g++ -o templatefunc.cpp.bin -std=c++17 -fconcepts templatefunc.cpp &&
./templatefunc.cpp.bin
Max(i, j): 39
Max(f1, f2): 20.7
Max(s1, s2): World
#include <iostream>
using std::cout;
using std::endl;
#include <iomanip>
using std::setw;
#include <typeinfo>
// define a class array of type T
// the type is not known yet and will
// be defined by instantiation
Groth / PE 2023 / Templates / Lecture 51/96
// of object of class array<T> from main
template<typename T> class array {
private:
int asize;
T *myarray; // we need a pointer here as we dont' know
// how many elements we will need
public:
// constructor with user pre-defined size
array (int s) {
asize = s;
myarray = new T[asize];
}
// class array member function to set
// element of myarray with type T values
void set ( int elem, T val) {
myarray[elem] = val;
return 0;
}
$ g++ -o arrayclass.cpp.bin -std=c++17 -fconcepts arrayclass.cpp &&
./arrayclass.cpp.bin
0 3 type: i
1 3 type: i
-----------------------------
elem 0: 3
----
0 3.4 type: f
1 2.8 type: f
Groth / PE 2023 / Templates / Lecture 56/96
2 0 type: f
-----------------------------
0 H type: c
1 E type: c
2 L type: c
3 L type: c
4 O type: c
-----------------------------
int main() {
// create a vector to store int
vector<int> vec = {1,2,3};
int i;
// display the original size of vec
cout << "vector size = " << vec.size() << endl;
// push 5 values into the vector
for(i = 0; i < 5; i++) {
vec.push_back(i);
}
Groth / PE 2023 / Templates / Lecture 65/96
// display extended size of vec
cout << "extended vector size = " << vec.size() << endl;
// access 4 values from the vector
for(i =0; i < 4; i++) {
cout << "value of vec [" << i << "] = " << vec[i] << endl;
}
// use algorithm for sorting
std::sort(vec.begin(), vec.end());
// use iterator to access the values
vector<int>::iterator v = vec.begin();
while( v != vec.end()) {
cout << "value of v = " << *v << endl;
v++;
}
return 0;
}
$ g++ -o vector.cpp.bin -std=c++17 -fconcepts vector.cpp &&
Groth / PE 2023 / Templates / Lecture 66/96
./vector.cpp.bin
vector size = 3
extended vector size = 8
value of vec [0] = 1
value of vec [1] = 2
value of vec [2] = 3
value of vec [3] = 0
value of v = 0
value of v = 1
value of v = 1
value of v = 2
value of v = 2
value of v = 3
value of v = 3
value of v = 4
https:
//www.acodersjourney.com/6-tips-supercharge-cpp-11-vector-performance/
int main() {
map<string,string> Kennzeichen;
Kennzeichen["HH"] = "Hansestadt Hamburg";
cout << Kennzeichen["HH"] << endl;
cout << "Groesse: " << Kennzeichen.size() << endl;
cout << Kennzeichen["HG"] << endl;
cout << "Groesse: " << Kennzeichen.size() << endl;
if (Kennzeichen.find("PM")==Kennzeichen.end()) {
cout << "PM Nicht gefunden!" << endl;
Groth / PE 2023 / Templates / Lecture 68/96
}
// shorter with c++20 'contains' returns bool
// if (Kennzeichen.contains("HH")) {
// cout << "HH gefunden!" << endl;
// }
// alternative until next year returns 0 or 1
if (Kennzeichen.count("HH")) {
cout << "HH gefunden!" << endl;
}
cout << "Groesse: " << Kennzeichen.size() << endl;
}
$ g++ -o map.cpp.bin -std=c++17 -fconcepts map.cpp && ./map.cpp.bin
Hansestadt Hamburg
Groesse: 1
Groesse: 2
PM Nicht gefunden!
Groth / PE 2023 / Templates / Lecture 69/96
HH gefunden!
Groesse: 2
ñ to avoid automatic extension of the map use find or count
first
ñ for more methods on maps see:
https://en.cppreference.com/w/cpp/container/map
ñ for more methods on vectors see:
https://en.cppreference.com/w/cpp/container/vector
http://www.modernescpp.com/index.php/c-17-the-improved-interface-of-the-associative-containers