Informatik W10
Levin Ceglie
Outline
- Quiz
- Klassen und Überladen von Funktionen
- Iteratoren
Klassen und Überladen von Funktionen
In C++ ist es tatsächlich möglich, dass zwei Funktionen denselben Namen haben, solange der Compiler eine andere Möglichkeit hat, die Funktionen voneinander zu unterscheiden. Dies geschieht über die sogenannte Funktionensigantur, welche im C++ Standard festgelegt wird (mehr dazu c++ - what is the difference between function declaration and signature? - Stack Overflow). Ein Teil diese Signatur zur Unterscheideung von Funktionen sind zum Beispiel Anzahl und Typen ihrer Argumente (Inputs).
Beispiel (Function Overloading)
Folgendes ist ein Beispiel zur Unterscheidung von Funktionen mittels unterschiedlicher Anzahl der Argumente:
int fun1(const int a) { ... }
int fun1(const int a, const int b) { ... }Und ein Beispiel zur Unterscheidung mittels verschiedenen Typen der Argumente:
int foo(const int a){ ... }
int foo(const float a){ ... }Beachte, dass bei dem folgenden Beispiel, der Compiler die Funktionen nicht unterscheiden kann (warum?), womit es zu einem Fehler kommt:
int foo(const int a){ ... }
int foo(const int b){ ... } // compiler errorAchtung: Der Rückgabetyp ist nicht Teil der Funktionensignatur, also
int foo(const int a){ ... }
double foo(const int a){ ... } // compiler errorAufgabe (Tribool)
Tribool ist eine dreiwertige Logik.

Frage: Wie könnte man das dies innehalb einer C++ Klasse modelieren?
Antwort: Verwende zum Beispiel einen unsigned int, welcher entweder 0, 1 oder 2 ist.
Frage: Wieso ist es eine gute Idee diese Variable als private zu markieren?
Antwort: Indem wir ihn privat machen, können wir sicherstellen dass er immer 0, 1 oder 2 ist. Die Möglichkeit, sich darauf zu verlassen macht die Implementierung bestimmter Methoden einfacher. Ausserdem können wir den Code in Zukunft leichter refaktorisieren. Zum Beispiel: Irgendwann werden wir vielleicht feststellen dass die Speicherung eines 32bit unsigned int nicht erforderlich ist, um 3 Werte darzustellen. Wenn der Wert privat ist, können wir ihn leicht in ein char ändern, ohne die öffentliche Schnittstelle der Klasse zu verändern.
Step 1:
Gemeinsam Constructors definieren und erklären wieso tribool.h und tribool.cpp aufgeteilt.
Step 2 & 3: 10-20’ Individuell
Lösung:
tribool.h
#pragma once
#include <string>
class Tribool {
private:
// 0 means false, 1 means unknown, 2 means true.
unsigned int value; // INV: value in {0, 1, 2}.
public:
// Constructor 1 (passing a numerical value)
// PRE: value in {0, 1, 2}.
// POST: tribool false if value was 0, unknown if 1, and true if 2.
Tribool(unsigned int value_int);
// Constructor 2 (passing a string value)
// PRE: value in {"true", "false", "unknown"}.
// POST: tribool false, true or unknown according to the input.
Tribool(std::string value_str);
// Member function string()
// POST: Return the value as string
std::string string() const;
// Operator && overloading
// POST: returns this AND other
Tribool operator&&(const Tribool& other) const;
};tribool.cpp
#include <iostream>
#include <cassert>
#include "tribool.h"
Tribool::Tribool(unsigned int value_int) : value(value_int) {
assert(value_int <= 2);
}
// Alternative
// Tribool::Tribool(unsigned int value_int) {
// value = value_int;
// assert(value_int <= 2);
// }
Tribool::Tribool(std::string value_str) {
assert(value_str == "true" || value_str == "unknown" || value_str == "false");
if (value_str == "true") {
value = 2;
} else if (value_str == "unknown") {
value = 1;
} else if (value_str == "false") {
value = 0;
}
}
std::string Tribool::string() const {
switch (value) {
case 0: return "false";
case 1: return "unknown";
case 2: return "true";
default: assert(false);
}
}
Tribool Tribool::operator&&(const Tribool& other) const {
Tribool result(std::min(value, other.value));
return result;
}Iteratoren
Container sind Objekte, die zum Speichern von Sammlungen von Elementen verwendet werden. Zu den gängigen C++-Containern gehören Vektoren, Mengen, und Listen. Eine vollständige Liste der Container in der C++-Standardbibliothek finden Sie hier: Containers library - cppreference.com.
Iteratoren werden verwendet, um Elemente in einem Container auf einheitliche Weise zu durchlaufen. Die Benutzer müssen (und sollten auch nicht) die internen Details eines Containers kennen, um ihn zu verwenden und über ihn zu iterieren. Sei c ein Container, dann
• it = c.begin(): Iterator zum ersten Element
• it = c.end(): Iterator hinter das letzte Element
• *it: greift das momentane Element zu
• ++it: Iterator um eins nach vorne schieben
Aufgabe (Find Max)
Gemeinsam die momentane find_max Funktion durchgehen.
Lösung:
// PRE: (begin < end) && (begin and end must be valid iterators)
// POST: Return the greatest element in the range [begin, end)
unsigned int find_max(std::vector<unsigned int>::iterator begin, std::vector<unsigned int>::iterator end) {
unsigned int max_value = 0;
for(; begin != end; ++begin) {
if (max_value < *begin) {
max_value = *begin;
}
}
return max_value;
}Aufgabe (The algorithm Library)
Die algorithm Library bietet eine Reihe von vordefinierten Funktionen um allgemeine Operationen mit Containern durchzuführen. Diese Funktionen sind so programmiert, dass sie für verschiedenen Containern wie Vektoren, Arrays, Listen usw. funktionieren und helfen bei der effizienten Durchführung von Aufgaben, ohne dass der Code von Grund auf neu geschrieben werden muss.
#include <iostream>
#include <vector>
#include <algorithm>
// POST: Reads a sequence terminated by a negative number into vec.
void input(std::vector<int>& vec) {
int e;
std::cin >> e;
while (e >= 0) {
vec.push_back(e);
std::cin >> e;
}
}
// POST: Prints the contents of the vector into stdout.
void print(std::vector<int>& vec) {
for (std::vector<int>::iterator it = vec.begin(); it != vec.end(); it++) {
std::cout << *it << " ";
}
std::cout << std::endl;
}
int main() {
std::vector<int> vec = std::vector<int>();
input(vec);
int largest_element = *std::max_element(vec.begin(), vec.end());
std::cout << "The largest element in the sequence: " << largest_element << std::endl;
std::sort(vec.begin(), vec.end());
std::cout << "Sorted vector: ";
print(vec);
}