Anhang R
Erweiterte Klasse CData2
Die Klasse CData, erweitert um die überladenen Operatoren <<, [ ] und Vergleichsfunktionen.
module;
#include <print>
#include <cstdlib>
#include <iostream>
#include <iomanip>
// Makro für Debug-Ausgaben
//#define TRACE_METH
#ifdef TRACE_METH
#define TRACE(T_) std::println("Obj-Nr:{} {}",objNum,T_);
#define TRACES(T_) std::println("Obj-Nr:{} {}",self.objNum,T_);
#else
#define TRACE(T_)
#define TRACES(T_)
#endif
export module CData2;
export class CData2
{
int* pData = nullptr; // Zeiger auf Datenfeld
size_t dSize; // Groesse Datenfeld
// Objektzaehler fuer Debug-Zwecke
inline static int objCount = 0;
int objNum; // Objektnummer
public:
// Standard-ctor (pData=nullptr!)
CData2();
// ctor mit Datenfeldgroesse
CData2(size_t _dSize);
// copy-ctor
CData2(const CData2& src);
// move-ctor
CData2(CData2&& src);
// Zuweisungsoperator
CData2& operator = (this CData2& self, const CData2& src);
// move-Zuweisungsopertor
CData2& operator = (this CData2& self, CData2&& src);
// dtor
~CData2();
// Ausgabe des Datenfeldes
friend std::ostream& operator << (std::ostream& out, const CData2& obj);
// Ueberladener Indexoperator
int& operator [] (size_t index);
// space-operator
auto operator <=> (this const CData2& self, const CData2& op2);
// Vergleich auf Gleichheit
bool operator == (const CData2& op2) const;
};
// Standard-ctor
CData2::CData2()
{
objNum = ++objCount;
TRACE(">>> ctor CData2()");
}
// ctor mit Datenfeldgroesse
CData2::CData2(size_t _dSize)
{
dSize = _dSize;
pData = new int[dSize];
for (size_t index = 0; index < dSize; index++)
pData[index] = std::rand() % 100;
objNum = ++objCount;
TRACE(">>> ctor CData2(size)");
}
// copy-ctor
CData2::CData2(const CData2& src) :
CData2(src.dSize)
{
for (size_t index = 0; index < dSize; index++)
pData[index] = src.pData[index];
objNum = ++objCount;
TRACE(">>> copy-ctor")
}
// move ctor
CData2::CData2(CData2&& src)
{
dSize = src.dSize;
pData = std::move(src.pData);
objNum = src.objNum;
src.pData = nullptr; // WICHTIG!!!!
TRACE(">>> move-ctor");
}
// Zuweisungsoperator
CData2& CData2::operator = (this CData2& self, const CData2& src)
{
if (&self == &src) // keine Zuweisung auf sich selbst!
return self;
delete[] self.pData; // bisherige Daten freigeben
self.dSize = src.dSize; // neue Daten uebernehmen
self.pData = new int[self.dSize];
for (size_t index = 0; index < self.dSize; index++)
self.pData[index] = src.pData[index];
TRACES("operator =");
return self;
}
// move-Zuweisungsopertor
CData2& CData2::operator = (this CData2& self, CData2&& src)
{
if (&self == &src) // keine Zuweisung auf sich selbst!
return self;
delete[] self.pData; // bisherige Daten loeschen
self.dSize = src.dSize; // neue Daten uebernehmen
self.pData = src.pData; // durch Zuweisung des Zeigers
src.pData = nullptr; // WICHTIG!!!!
TRACES("move-operator =");
return self;
}
// dtor
CData2::~CData2()
{
delete[] pData;
TRACE("<<< dtor");
}
// Ueberladener Indexoperator
int& CData2::operator [] (size_t index)
{
// size_t ist immer ein unsigned Integerwert
// und kann damit niemals <0 sein
if (index >= dSize)
index = dSize-1;
return pData[index];
}
// Ausgabe des Datenfeldes
export std::ostream& operator << (std::ostream& out, const CData2& obj)
{
out << "Daten Objekt " << obj.objNum << ":\t\n";
for (size_t index = 0; index < obj.dSize; index++)
out << std::setw(3) << obj.pData[index] << ',';
out << '\n';
return out;
}
// space-operator
auto CData2::operator <=> (this const CData2& self, const CData2& op2)
{
// Zuerst die Groesse vergleichen
if (auto cmp = self.dSize <=> op2.dSize; cmp != 0)
return cmp;
// Nun die Daten vergleichen
// Aufruf des operators ==
return (self == op2) <=> true;
}
// Vergleich auf Gleichheit
bool CData2::operator == (const CData2& op2) const
{
if (dSize != op2.dSize)
return false;
// Nun die Daten vergleichen
bool isEqual = true;
for (size_t index = 0; index < dSize; index++)
{
// Wenn Daten ungleich, Schleife verlassen
if (pData[index] != op2.pData[index])
{
isEqual = false;
break;
}
}
return isEqual;
}