Anhang Q

CData Klasse

In einigen Übung wird die Klasse CData benötigt, die in der Modul-Datei CData.cxx bei den Musterlösungen definiert ist. Durch Definition des Symbols TRACE_METH in Zeile 7 kann der Aufruf der Methoden verfolgen werden.

module;
#include <print>
#include <cstdlib>
#include <iostream>

// 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 CData;
export class CData
{
    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!)
    CData();
    // ctor mit Datenfeldgroesse
    CData(size_t _dSize);
    // copy-ctor
    CData(const CData& src);
    // move-ctor
    CData(CData&& src);
    // Zuweisungsoperator
    CData& operator = (this CData& self, const CData& src);
    // move-Zuweisungsopertor
    CData& operator = (this CData& self, CData&& src);
    // dtor
    ~CData();
    // Ausgabe des Datenfeldes
    void Print() const;
};
CData::CData()
{
    objNum = ++objCount;
    TRACE(">>> ctor CData()");
}
// ctor mit Datenfeldgroesse
CData::CData(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 CData(size)");
}
// copy-ctor
CData::CData(const CData& src) :
    CData(src.dSize)
{
    for (size_t index = 0; index < dSize; index++)
        pData[index] = src.pData[index];
    TRACE(">>> copy-ctor")
}
// move ctor
CData::CData(CData&& src)
{
    dSize = src.dSize;
    pData = std::move(src.pData);
    src.pData = nullptr;    // WICHTIG!!!!
    objNum = ++objCount;
    TRACE(">>> move-ctor");
}
// Zuweisungsoperator
CData& CData::operator = (this CData& self, const CData& 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
CData& CData::operator = (this CData& self, CData&& 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
CData::~CData()
{
    delete[] pData;
    TRACE("<<< dtor");
}
// Ausgabe des Datenfeldes
void CData::Print() const
{
    std::println("Daten Objekt {}:\t", objNum);
    for (size_t index = 0; index < dSize; index++)
        std::print("{:3},", pData[index]);
    std::println();
}