Geschiedenis van de vraag:
C++ is gebaseerd op C, dat een klein aantal ingebouwde types bood: getallen, karakters, arrays. Naarmate de taal zich ontwikkelde, kwamen concepten zoals structuren, klassen, enumeraties — dit werden gebruikersgedefinieerde types.
Probleem:
Het gegevenstype in een programma bepaalt hoeveel geheugen een variabele zal innemen, hoe het geïnitialiseerd, gekopieerd, vernietigd en vergeleken wordt. Ingebouwde types hebben bepaald gedrag volgens de standaard, terwijl gebruikersgedefinieerde types expliciete beschrijving van alle aspecten vereisen. Fouten in het beheer van gebruikersgedefinieerde types kunnen leiden tot crashes, lekken, oneerlijke vergelijkingen van objecten, enz.
Oplossing:
Ingebouwde types zijn int, float, double, char, bool en andere "primitive" types. Gebruikersgedefinieerde types zijn elk structuren, klassen, unies die door jou zijn gemaakt. Voor complexe taken is het nodig om gebruikersgedefinieerde types in te voeren met correcte semantiek van kopiëren, vergelijken en resourcebeheer.
Code voorbeeld:
// Ingebouwd type int x = 5; // Gebruikersgedefinieerd type struct Point { double x, y; }; Point a = {1.0, 2.0}; // Klasse met resources class MyFile { public: MyFile(const std::string& fn) : f(fopen(fn.c_str(), "r")) {} ~MyFile() { if (f) fclose(f); } private: FILE* f; };
Kunnen gebruikersgedefinieerde types zich volledig als ingebouwde types gedragen (bijvoorbeeld, vergeleken worden via == "out of the box")?
Nee, de vergelijking == werkt standaard alleen vanaf C++20 via defaulted operator==, daarvoor was expliciete definitie vereist.
Kan ik de copy constructor en destructor niet implementeren als de klasse alleen een ruwe pointer (int, FILE, etc.) bevat?**
Nee, in dat geval zal de standaard kopie "shallow" zijn, wat kan leiden tot leaks of dubbele vrijgave van geheugen/resource. Het is nodig om de "Rule of Five" te implementeren.
Zal de standaardwaarde van de structuur op nul worden geïnitialiseerd (Point p;)?
Nee, een lokale structuur kan niet-geïnitialiseerd zijn, de inhoud van het geheugen is willekeurig. Gebruik expliciete initialisatie.
Negatieve case:
Een wrapper klasse voor een bestand heeft geen destructor geïmplementeerd. Het programma werkte, totdat het duizenden bestanden begon te verwerken zonder de descriptors te sluiten.
Voordelen: minder code, vereenvoudigde weergave Nadelen: resource leaks, onbetrouwbaar gedrag
Positieve case:
De klasse implementeert RAII - het bestand wordt geopend in de constructor, wordt gesloten in de destructor, kopiëren is verboden.
Voordelen: betrouwbaarheid, veiligheid, schone interface Nadelen: noodzaak om de "Rule of Five" te onthouden en meer code te schrijven