Kapitel 9

Alle Codedateien dieses Kapitels herunterladen

09_1_1_Sizeof.cpp

Datei herunterladen

#include <iostream>
#include <string>

struct Example
{
  int a = 11;
  int b = 21;
};

struct Example2
{
  int a = 0;
  int b = 0;
  std::string c;
};

int main()
{
  // sizeof() gibt die Größe im Speicher an.
  // Allerdings hat diese Funktion so ihre Fallstricke.
  // Sollten Sie sie in eigenem Code verwenden, empfehle
  // ich Ihnen zwei Dinge:
  // 1) Nochmals überlegen, ob Sie sie WIRKLICH brauchen
  // 2) Weiteres Wissen im Internet anlesen
  std::cout << sizeof(int) << std::endl;
  std::cout << sizeof(char*) << std::endl;
  std::cout << sizeof(std::string) << std::endl;

  std::cout << sizeof(Example) << std::endl;
  std::cout << sizeof(Example2) << std::endl;
  std::cout << sizeof(std::string*) << std::endl;
  return 0;
}

09_2_1_Beispielzeiger.cpp

Datei herunterladen

#include <iostream>
int main()
{
  int number = 256;
  int* pointer = new int(42);
  int* pointerToNumber = &number;

  std::cout << "number: " << number << std::endl
    << "pointer: " << pointer << std::endl
    << "pointerToNumber: " << pointerToNumber << std::endl;

  return 0;
}
// Hinweis: Dieses Programm enthält ein Memory-Leak,
// welches erst auf einer der nächsten Buchseiten
// behoben wird!

09_2_2_BeispielzeigerDereferenziert.cpp

Datei herunterladen

#include <iostream>
int main()
{
  int number = 256;
  int* pointer = new int(42);
  int* pTN = &number;  // Abkürzung für: pointerToNumber
  int* pTN2 = &number;
  int* pointerToNull = nullptr;

  std::cout << "Name     | Adresse        | Wert\n"
    << "--------------------------------\n"
    << "pointer  |" << pointer << "|" << *pointer << "\n"
    << "pTN      |" << pTN     << "|" << *pTN << "\n"
    << "pTN2     |" << pTN2    << "|" << *pTN2 << "\n\n";

  // Änderung des Wertes
  number = 177;
  std::cout << "Name     | Adresse        | Wert\n"
    << "--------------------------------\n"
    << "pointer  |" << pointer << "|" << *pointer << "\n"
    << "pTN      |" << pTN     << "|" << *pTN << "\n"
    << "pTN2     |" << pTN2    << "|" << *pTN2 << "\n";
  return 0;
}
// Hinweis: Dieses Programm enthält ein Memory-Leak,
// welches erst auf einer der nächsten Buchseiten
// behoben wird!

09_2_3_PointerToNull.cpp

Datei herunterladen

#include <iostream>
int main()
{
  int* pointerToNull = nullptr;
  if (pointerToNull == nullptr)
  {
    std::cout << "Nullptr: " << pointerToNull << std::endl;
  }
  else
  {
    std::cout << *pointerToNull << std::endl;
  }
  return 0;
}

09_2_4_PfeilOperator.cpp

Datei herunterladen

#include <iostream>
#include <string>

int main()
{
  std::string* stringPointer = new std::string("Hello");
  std::cout << stringPointer->size() << std::endl;
  for (char c : *stringPointer)
  {
    std::cout << c;
  }
  std::cout << std::endl;
  for (int i = 0; i < stringPointer->size(); i++)
  {
    std::cout << stringPointer->at(i);
  }
  return 0;
}
// Hinweis: Dieses Programm enthält ein Memory-Leak,
// welches erst auf einer der nächsten Buchseiten
// behoben wird!

09_2_5_SpeicherFreigeben.cpp

Datei herunterladen

#include <iostream>
int main()
{
  int* pointer = new int(42);
  std::cout << *pointer << std::endl;
  delete pointer;
  // Ein Dereferenzieren nach einem delete würde zu einem
  // Crash führen!
  // std::cout << *pointer << std::endl;
  return 0;
}

09_2_6_Zombievariable.cpp

Datei herunterladen

#include <iostream>
int main()
{
  int* pointerToNumber = nullptr;
  if (true)
  {
    int number = 17;
    pointerToNumber = &number;
  }
  // Das kann schwerwiegende Folgen haben:
  std::cout << *pointerToNumber << std::endl;
  return 0;
}

09_3_SmartPointer.cpp

Datei herunterladen

#include <iostream>
#include <memory>  // Für den Typ des Smart Pointers

int main()
{
  std::shared_ptr<int> pointer = std::make_shared<int>(4);
  std::cout << "1: *pointer " << *pointer << std::endl;
  // Ohne Angabe sind Smart Pointer AUTOMATISCH nullptr
  std::shared_ptr<int> pointer2;
  // Ausgabe der Adresse: (Dereferenzieren würde crashen!)
  std::cout << "2: pointer2 " << pointer2 << std::endl;

  if (true)
  {
    std::shared_ptr<int> pointer3;
    pointer3 = std::make_shared<int>(35);
    pointer2 = pointer3;
    std::cout << "3: *pointer2 " << *pointer2 << std::endl;

    // Wie bei normalen Zeigern auch ändert sich der
    // Wert bei allen, die auf denselben Speicher zeigen
    *pointer3 = 11;
    std::cout << "4: *pointer2 " << *pointer2 << std::endl;
  }
  // pointer3 verlässt den Gültigkeitsbereich, aber pointer2
  // hat immer noch Zugriff auf den gemeinsamen Speicher.
  std::cout << "5: *pointer2 " << *pointer2 << std::endl;
  // Das Prüfen auf nullptr geht genauso wie bei Zeigern:
  if (pointer2 != nullptr)
  {
    std::cout << "6: pointer2 ist nicht Null" << std::endl;
  }
  return 0;
}
// Nach Ende des Programms wurden pointer und
// pointer2 automatisch aufgeräumt

09_4_1_DurchNullTeilen.cpp

Datei herunterladen

#include <iostream>
#include <exception>

double divide(int a, int b)
{
  if (b == 0)
  {
    throw std::exception("Nenner ist null");
  }
  return a / static_cast<double>(b);
}

int main()
{
  std::cout << divide(10, 3) << std::endl;
  std::cout << divide(10, 0) << std::endl;
  return 0;
}

09_4_2_FehlerAbfangen.cpp

Datei herunterladen

#include <iostream>
#include <exception>

double divide(int a, int b)
{
  if (b == 0)
  {
    throw std::exception("Nenner ist null");
  }
  return a / static_cast<double>(b);
}

int main()
{
  std::cout << divide(10, 3) << std::endl;
  try
  {
    std::cout << divide(10, 0) << std::endl;
    std::cout << "Kein Fehler aufgetreten!" << std::endl;
  }
  catch (std::exception& ex)
  {
    std::cerr << "Fehler abgefangen: " << ex.what() << std::endl;
  }
  std::cout << "Programmende" << std::endl;
  return 0;
}

09_4_3_StoiFehler.cpp

Datei herunterladen

#include <iostream>
#include <exception>
#include <string>

int main()
{
  std::cout << std::stoi("123") << std::endl;
  try
  {
    std::cout << std::stoi("abc") << std::endl;
  }
  catch (std::exception& e)
  {
    std::cerr << e.what() << std::endl;
  }
  return 0;
}

09_5_1_Aufteilung

Aufteilung.cpp

Datei herunterladen

#include <iostream>
#include "Aufteilung.h"

int sum(int a, int b)
{
  return a + b;
}

Person::Person(std::string name)
  : name(name)
{
}

void Person::printName()
{
  std::cout << "Name: " << name << std::endl;
}

int main()
{
  std::cout << "1+2 = " << sum(1, 2) << std::endl;
  Person hans("Hans Wurst");
  hans.printName();
  return 0;
}

/*

class Person
{
 public:
  Person(std::string name)
    : name(name)
  {
  }
  void printName()
  {
    std::cout << "Name: "
      << name << std::endl;
  }
 private:
  const std::string name;
};

*/

Aufteilung.h

Datei herunterladen

#pragma once
#include <string>

int sum(int a, int b);

class Person
{
 public:
  Person(std::string name);
  void printName();
 private:
  const std::string name;
};

09_5_2_Beispielfabrik

Beispielfabrik.cpp

Datei herunterladen

#include "Robot.h"
#include "Factory.h"

int main()
{
  Factory factory;
  factory.addRobot(Robot("WALL-E"));
  factory.addRobot(Robot("R2-D2"));
  factory.startWork();
  return 0;
}

Factory.cpp

Datei herunterladen

#include "Factory.h"

void Factory::addRobot(const Robot& robot)
{
  robots.push_back(robot);
}
void Factory::startWork()
{
  for (Robot& robot : robots)
  {
    robot.work();
  }
}

Factory.h

Datei herunterladen

#pragma once
#include <vector>
#include "Robot.h"

class Factory
{
 public:
  void addRobot(const Robot& robot);
  void startWork();
 private:
  std::vector<Robot> robots;
};

Robot.cpp

Datei herunterladen

#include "Robot.h"
#include <iostream>

Robot::Robot(const std::string& name) : name(name)
{
}
void Robot::work()
{
  std::cout << name << ": Arbeit, Arbeit!" << std::endl;
}

Robot.h

Datei herunterladen

#pragma once
#include <string>

class Robot
{
 public:
  Robot(const std::string& name);
  void work();
 private:
  const std::string name;
};