Structuren en hun toepassingen c. Structuren in C en hun overdracht

Laatste update: 09.10.2017

Vroeger gebruikten we om klassen te definiëren trefwoord klas. C++ biedt echter een andere manier om te definiëren aangepaste typen, namelijk het gebruik van structuren. Deze methode werd door de C++-taal geërfd van de C-taal.

Een structuur in C++ is een afgeleid gegevenstype dat een specifieke entiteit vertegenwoordigt, net als een klasse. Vaak worden structuren in relatie tot C++ ook wel klassen genoemd. En in werkelijkheid zijn de verschillen tussen hen niet zo groot.

Het sleutelwoord struct wordt gebruikt om een ​​structuur te definiëren, en het formaat van de definitie is als volgt:

Structuur struct_naam (struct_components);

Structuurnaam vertegenwoordigt een willekeurige identificatie, waarop dezelfde regels van toepassing zijn als voor het benoemen van variabelen.

Na de structuurnaam in krullende beugels fit Structuur_componenten, die een reeks beschrijvingen vertegenwoordigen van de objecten en functies waaruit de structuur bestaat.

Laten we bijvoorbeeld definiëren eenvoudigste structuur:

#erbij betrekken #erbij betrekken struct person (int age; std::stringnaam; ); int main() ( persoon tom; tom.name = "Tom"; tom.age = 34; std::cout<< "Name: " << tom.name << "\tAge: " << tom.age << std::endl; return 0; }

Dit definieert een persoonsstructuur die twee elementen heeft: leeftijd (vertegenwoordigt een int-type) en naam (vertegenwoordigt een string).

Zodra de structuur is gedefinieerd, kunnen we deze gebruiken. Om te beginnen kunnen we een structuurobject definiëren - in wezen een gewone variabele die het hierboven gemaakte type vertegenwoordigt. Nadat u een structuurvariabele hebt gemaakt, heeft u ook toegang tot de elementen ervan - haal hun waarden op of, omgekeerd, wijs er nieuwe waarden aan toe. Om toegang te krijgen tot de elementen van een structuur, gebruikt u de "punt"-bewerking:

Structuurvariabelenaam.elementnaam

In wezen is een structuur vergelijkbaar met een klasse, dat wil zeggen dat u met behulp van structuren ook entiteiten kunt definiëren voor gebruik in een programma. Tegelijkertijd zijn alle leden van de structuur waarvoor de toegangsspecificatie (openbaar, privé) niet wordt gebruikt standaard openbaar. Terwijl in een klasse alle leden waarvoor de toegangsspecificatie niet is gespecificeerd, privé zijn.

Bovendien kunnen we een structuur initialiseren door waarden aan de variabelen toe te wijzen met behulp van de initialisatiesyntaxis:

Persoon tom = ( 34, "Tom" );

Het initialiseren van structuren is vergelijkbaar met het initialiseren van arrays: waarden voor structuurelementen worden op volgorde tussen accolades doorgegeven. Omdat de eerste eigenschap in de persoonsstructuur er een is die het int-type vertegenwoordigt (een getal), staat het getal eerst tussen accolades. En zo verder voor alle elementen van de structuur in volgorde.

Bovendien kunnen we elke klasse als structuur weergeven en omgekeerd. Neem bijvoorbeeld de volgende klasse:

Klasse Persoon ( public: Person(std::string n, int a) ( naam = n; leeftijd = a; ) void move() ( std::cout<< name << " is moving" << std::endl; } void setAge(int a) { if (a >0 && een< 100) age = a; } std::string getName() { return name; } int getAge() { return age; } private: std::string name; int age; };

Deze klasse definieert de essentie van een persoon en bevat een aantal private en publieke variabelen en functies. In plaats van een klasse kunnen we een structuur gebruiken om dezelfde entiteit te definiëren:

#erbij betrekken #erbij betrekken struct gebruiker ( public: user(std::string n, int a) ( naam = n; leeftijd = a; ) void move() ( std::cout<< name << " is moving" << std::endl; } void setAge(int a) { if (a >0 && een< 100) age = a; } std::string getName() { return name; } int getAge() { return age; } private: std::string name; int age; }; int main() { user tom("Tom", 22); std::cout << "Name: " << tom.getName() << "\tAge: " << tom.getAge() << std::endl; tom.setAge(31); std::cout << "Name: " << tom.getName() << "\tAge: " << tom.getAge() << std::endl; return 0; }

En wat het eindresultaat van het programma betreft, zouden we geen enkel verschil zien.

Wanneer structuren gebruiken? In de regel worden structuren gebruikt om gegevens te beschrijven die slechts een reeks openbare attributen hebben: openbare variabelen. Bijvoorbeeld zoals dezelfde persoonsstructuur die aan het begin van het artikel is gedefinieerd. Soms worden dergelijke entiteiten ook wel genoemd geaggregeerde klassen(samengestelde klassen).

Structuren

Zoals u al weet, zijn klassen referentiegegevenstypen. Dit betekent dat objecten van een bepaalde klasse toegankelijk zijn via referentie, in tegenstelling tot waarden van eenvoudige typen die direct toegankelijk zijn. Maar soms blijkt directe toegang tot objecten als waarden van eenvoudige typen nuttig te zijn, bijvoorbeeld om de programma-efficiëntie te vergroten. Elke toegang tot objecten (zelfs de kleinste) via referentie gaat immers gepaard met extra kosten voor het verbruik van computerbronnen en RAM.

Om dergelijke problemen op te lossen, biedt C# structuur, die vergelijkbaar is met een klasse, maar een waardetype is in plaats van een referentiegegevenstype. Die. structs verschillen van klassen in de manier waarop ze in het geheugen worden opgeslagen en hoe ze worden benaderd (klassen zijn referentietypen die op de heap zijn toegewezen, structs zijn waardetypen die op de stapel zijn toegewezen), en ook in bepaalde eigenschappen (structs ondersteunen bijvoorbeeld geen overerving ). Om prestatieredenen gebruikt u structuren voor kleine gegevenstypen. Qua syntaxis lijken structuren echter sterk op klassen.

Het belangrijkste verschil is dat ze worden aangegeven met behulp van struct-trefwoord in plaats van klasse. Het volgende is de algemene vorm van een structuurdeclaratie:

structnaam: interfaces ( // lidverklaringen )

waarbij naam de specifieke naam van de structuur aangeeft.

Net als klassen heeft elke structuur zijn eigen leden: methoden, velden, indexeerders, eigenschappen, operatormethoden en gebeurtenissen. Structuren kunnen ook constructors definiëren, maar geen destructors. U kunt echter geen standaardconstructor voor een structuur definiëren (dat wil zeggen: een constructor zonder parameters). Het punt is dat de standaardconstructor automatisch voor alle constructies wordt bepaald en niet kan worden gewijzigd. Deze constructor initialiseert de velden van de structuur met standaardwaarden. En aangezien structuren geen overerving ondersteunen, kunnen hun leden niet worden gespecificeerd als abstract, virtueel of beschermd.

Met behulp van kan een structuurobject worden gemaakt exploitant nieuw op dezelfde manier als een klasseobject, maar dit is niet bijzonder noodzakelijk. Wanneer de nieuwe operator wordt gebruikt, wordt immers de standaardconstructor aangeroepen. En als deze operator niet wordt gebruikt, wordt het object nog steeds gemaakt, ook al is het niet geïnitialiseerd. In dit geval moeten alle leden van de structuur handmatig worden geïnitialiseerd.

Laten we een voorbeeld bekijken van het gebruik van structuren:

Systeem gebruiken; naamruimte ConsoleApplication1 ( // Maak een structuurstructuur UserInfo ( public string Name; public byte Age; public UserInfo(string Name, byte Age) ( this.Name = Naam; this.Age = Age; ) public void WriteUserInfo() ( Console. WriteLine ("Naam: (0), leeftijd: (1)", Naam, Leeftijd klasse Programma ( static void Main() ( UserInfo user1 = new UserInfo("Alexandr", 26); Console.Write("user1 : "); user1.WriteUserInfo(); UserInfo user2 = new UserInfo("Elena",22); Console.Write("user2: "); user2.WriteUserInfo(); // Toon het belangrijkste verschil tussen structuren en klassen user1 = gebruiker2; gebruiker2.Naam = "Natalya"; gebruiker2.Write("\nuser1: "); Console.Write("gebruiker2: ") );

Merk op dat wanneer een structuur aan een andere wordt toegewezen, er een kopie van het object wordt gemaakt. Dit is een van de belangrijkste verschillen tussen een structuur en een klasse. Wanneer een verwijzing naar de ene klasse wordt toegewezen aan een verwijzing naar een andere klasse, is het resultaat dat de verwijzing aan de linkerkant van de toewijzingsinstructie naar hetzelfde object verwijst als de verwijzing aan de rechterkant. En wanneer een variabele in de ene structuur wordt toegewezen aan een variabele in een andere structuur, wordt er een kopie van het structuurobject aan de rechterkant van de toewijzingsinstructie gemaakt.

Als het vorige voorbeeld de klasse UserInfo had gebruikt in plaats van een struct, zou het volgende het resultaat zijn geweest:

Doel van structuren

In verband met het bovenstaande rijst een redelijke vraag: waarom is een structuur opgenomen in C# als deze bescheidener mogelijkheden heeft dan een klasse? Het antwoord op deze vraag ligt in het verbeteren van de efficiëntie en productiviteit van programma's. Structuren zijn waardetypen en kunnen daarom rechtstreeks worden gemanipuleerd in plaats van door middel van referentie. Om met de structuur te werken is er dus helemaal geen variabele van een referentietype nodig, en dit betekent in sommige gevallen aanzienlijke besparingen in RAM.

Voordat we klassen in C++ gaan bestuderen, zullen we kijken naar een gegevenstype dat lijkt op een klasse: structs. Structuren zijn handig wanneer we verschillende variabelen van verschillende typen onder één naam moeten combineren. Dit maakt het programma compacter en flexibeler om wijzigingen door te voeren. Structuren zijn ook onmisbaar als het nodig is om bepaalde gegevens te groeperen, bijvoorbeeld een record uit een database of een contactpersoon uit een adresboek. In het laatste geval bevat de structuur contactgegevens zoals naam, adres, telefoonnummer, etc.

Syntaxis

Tijdens het schrijven van een programma moet u mogelijk verschillende gegevens groeperen. Mogelijk wilt u bijvoorbeeld de coördinaten van sommige objecten en hun namen opslaan. Je kunt dit doen met:

Int x_coor; int y_coor; tekenreeksnamen;

Maar omdat elk element van de ene array met een ander element is verbonden, zul je, als je er één verandert, ook de rest moeten veranderen. En hoe meer gegevens je moet combineren, hoe complexer zo'n programma zal zijn. Daarom gebruiken we om verschillende gegevens te combineren structuren .

Advertentie-indeling structuur ziet er als volgt uit:

Structure Car (int x_coor; int y_coor; stringnaam; );

Door een structuur te declareren, introduceren we ons eigen gegevenstype in het programma, dat we op dezelfde manier kunnen gebruiken als standaardtypen, d.w.z. De declaratie van een variabele van ons type zal als volgt zijn:

Structuurnaam variabelenaam;

structName is de naam van de structuur, variabeleName is de naam van de variabele.

x_coor, y_coor en naam - velden onze structuur. Wanneer we een structuur declareren, creëren we een samengesteld gegevenstype dat kan worden gebruikt om variabelen te maken die meerdere waarden combineren (bijvoorbeeld coördinaten en een naam). Binnen de structuur geven we elk veld een naam, zodat we vervolgens met de naam naar deze waarde kunnen verwijzen.

Gebruik een punt om toegang te krijgen tot de velden van de structuur:

// declareer de Car-variabele myCar; // en gebruik het myCar.x_coor = 40; mijnCar.y_coor = 40; mijnCar.name = "Porche";

Zoals u kunt zien, kunt u zoveel velden in de structuur opslaan als u wilt, en deze kunnen verschillende typen hebben.

Laten we eens kijken naar een voorbeeld dat de combinatie van arrays en structuren demonstreert.

#erbij betrekken naamruimte std gebruiken; struct PlayerInfo (int skill_level; stringnaam; ); naamruimte std gebruiken; int main() ( // net als bij reguliere typen kun je een reeks structuren declareren PlayerInfo-spelers; for (int i = 0; i< 5; i++) { cout << "Please enter the name for player: " << i << "\n"; // сперва получим доступ к элементу массива, используя // обычный синтаксис для массивов, затем обратимся к полю структуры // с помощью точки cin >> spelers[ i ].naam;<< "Please enter the skill level for " << players[ i ].name << "\n"; cin >uit< 5; ++i) { cout << players[ i ].name << " is at skill level " << players[i].skill_level << "\n"; } }

> spelers[ i ].skill_level;

) voor (int i = 0; ik

Net als bij eenvoudige typen (bijvoorbeeld int), kunt u arrays van structuren maken. En werk met elk element van deze array op dezelfde manier als met een afzonderlijke variabele. Om toegang te krijgen tot het naamveld van het eerste element van een reeks structuren, schrijft u eenvoudigweg:

Spelers[ 0 ].naam

Structuren en functies

Heel vaak moet je functies schrijven die structuren als argumenten gebruiken of een structuur retourneren. Als je bijvoorbeeld een arcadespel met een kleine ruimte moet schrijven, heb je mogelijk een functie nodig om een ​​nieuwe vijand te initialiseren:

Structureer EnemySpaceShip ( int x_coördinaat; int y_coördinaat; int wapen_kracht; ); EnemySpaceShip getNewEnemy();

De functie getNewEnemy zou een structuur met geïnitialiseerde velden moeten retourneren:

EnemySpaceShip getNewEnemy() ( EnemySpaceShip schip; ship.x_coördinaat = 0; ship.y_coördinaat = 0; ship.weapon_power = 20; retourschip; )

Deze functie retourneert feitelijk een kopie van het gemaakte lokale variabele schip. Dit betekent dat elk veld van de structuur naar een nieuwe variabele wordt gekopieerd. In ons geval valt het kopiëren van een klein aantal velden niet op, maar als je met grote hoeveelheden data werkt, moet je onnodige handelingen vermijden. Hierover vertellen we meer in het artikel over pointers.

Om een ​​nieuwe variabele te verkrijgen, gebruiken we dus de volgende code:

EnemySpaceShip-schip = getNewEnemy();

Nu kan deze variabele als een reguliere structuur worden gebruikt.

U kunt structuren als volgt aan een functie doorgeven:

EnemySpaceShip-upgradeWapens (EnemySpaceShip-schip) ( ship.weapon_power += 10; retourschip; )

Wanneer we een structuur doorgeven aan een functie, wordt deze gekopieerd, net zoals wanneer we een structuur retourneren. Daarom gaan alle wijzigingen die binnen de functie zijn aangebracht verloren, dus retourneren we de structuur na de wijziging.

De functie gebruiken:

Schip = upgradeWapens(schip);

Structureer EnemySpaceShip ( int x_coördinaat; int y_coördinaat; int wapen_kracht; ); EnemySpaceShip getNewEnemy() ( EnemySpaceShip schip; ship.x_coördinaat = 0; ship.y_coördinaat = 0; ship.weapon_power = 20; retourschip; ) EnemySpaceShip upgradeWeapons(EnemySpaceShip schip) ( ship.weapon_power += 10; retourschip; ) int main () ( EnemySpaceShip vijand = getNewEnemy(); vijand = upgradeWapens(vijand); )

Wegwijzers

Als u met een structuur werkt, moet u voor toegang tot variabelen de operator “->” gebruiken in plaats van een punt. Alle aanwijzereigenschappen blijven ongewijzigd. Voorbeeld:

#erbij betrekken naamruimte std gebruiken; struct xampl(int x;); int main() ( xampl structuur; xampl *ptr; structure.x = 12; ptr = cout<< ptr->X; cin.get(); )

Een structuur is een geaggregeerd gegevenstype, omdat deze elementen van verschillende typen kan bevatten. De syntaxis voor het declareren van een structuur in C++ verschilt van die in C. Hoewel de C-versie correct blijft voor C++. Het blijkt dat je in C++ twee stijlen voor het declareren van structuren kunt gebruiken, maar in C kun je er maar één gebruiken. Laten we eens kijken naar de syntaxis voor het declareren van een structuur in C++:

Structuurnaam (type atrib; // andere elementen van de structuur) structVar1, structVar2, ...;

  • struct is het sleutelwoord waarmee de definitie van de structuur begint
  • Naam — structuurnaam
  • type — gegevenstype van structuurelement
  • atrib - structuurelement
  • structVar1-2 - structurele variabelen

Een structuurdeclaratie moet altijd beginnen met het sleutelwoord struct. Het is niet nodig dat de structuur een naam heeft, maar dan moeten bij zo'n structuur structuurvariabelen worden gedeclareerd tussen de sluitende accolade en de puntkomma, regel 5. De structuurdeclaratie moet accolades bevatten; waarvan de attributen worden gedeclareerd (elementen), regel 3. Structurele variabelen zijn bij het declareren van een structuur optioneel, regel 5.

Omdat een structuur een gegevenstype is, moet u, om dit gegevenstype te gebruiken, een structuurvariabele declareren en in plaats van het gegevenstype de naam van de structuur opgeven.

struct_name structVariabele;

Syntaxis voor het declareren van een structuur in C:

Typedef struct naam ( type atrib1; type atrib2; // andere elementen van de structuur... ) newStructName structVar;

De syntaxis voor het declareren van een structuur in de C-taal heeft twee opties. P Laat eerst het trefwoord weg typedef , met de naam newStructName wordt ook niet gebruikt, en de naam van de structuur, dan is het noodzakelijk om structuurvariabelen te gebruiken bij het declareren van de structuur - structVar , regel 6. Kijk naar het voorbeeld:

Structuurnaam structVar;

Of u kunt een typedef gebruiken om een ​​alias voor de newStructName-structuur te declareren, een alias:

NewStructName structVar;

Hoe dan ook, als je een pointer naar een structuur binnen een structuur wilt declareren, moet je de eerste syntaxis gebruiken:

Structuurnaam *struct_instance; // verwijzing naar structuur

Een verwijzing naar een structuur declareren

De syntaxis voor het declareren van een pointer naar een structuur in C is dubbelzinnig. Als u in C geen typedef gebruikt bij het definiëren van een structuur, dan is het verplicht om structuurvariabelen te gebruiken tussen de sluitende accolade en de puntkomma.
In C++ is dit niet vereist. Om een ​​pointer naar een structuur te declareren, plaatst u in C++ eenvoudigweg de naam van de structuurvariabele vooraf met een pointerteken - * .

Structuurnaam *structVar; // verwijzing naar structuurstructuurnaam

NieuweStructNaam *structVar; // newStructName moet worden gedeclareerd met typedef

of zo, ook voor SI:

Structuurnaam *structVar;

Toegang tot structuurelementen

Toegang tot structuurelementen is net zo eenvoudig als het gebruik van het puntsymbool. Laten we aannemen. dat we een structuurvariabele hebben genaamd auto en een element genaamd snelheid, waar we nu toegang toe zullen krijgen:

Autosnelheid;

Opmerking: deze methode om toegang te krijgen tot de elementen van een structuur werkt alleen als de structuur geen verwijzing naar een structuur is.

Toegang tot structuuraanwijzerelementen

Om toegang te krijgen tot elementen van een structuur via een verwijzing naar de structuur, gebruikt u in plaats van de puntoperator de pijl -> operator:

CarPtr->snelheid;

P.S.: Aan alle bezitters van Android-smartphones presenteer ik een goede selectie GPS-navigatieprogramma's voor Android. De lijst bevat ongeveer 20 softwareproducten. U kunt ze allemaal downloaden en op uw apparaat installeren. Alle programma's zijn helemaal gratis.

Laatste update: 10/02/2018

Samen met klassen vertegenwoordigen structuren een andere manier om eigen gegevenstypen te creëren in C#. Bovendien zijn veel primitieve typen, bijvoorbeeld int, double, enz., in wezen structuren.

Laten we bijvoorbeeld een structuur definiëren die een persoon vertegenwoordigt:

Structure User ( publieke stringnaam; public int age; public void DisplayInfo() ( Console.WriteLine($"Name: (name) Age: (age)"); ) )

Net als klassen kunnen structs status opslaan als variabelen en gedrag definiëren als methoden. In dit geval worden dus twee variabelen gedefinieerd: naam en leeftijd om respectievelijk de naam en leeftijd van een persoon op te slaan, en de DisplayInfo-methode om informatie over de persoon weer te geven.

We gebruiken deze structuur in het programma:

Systeem gebruiken; naamruimte HelloApp ( struct User ( public string name; public int age; public void DisplayInfo() ( Console.WriteLine($"Name: (name) Age: (age)"); ) ) class Program ( static void Main(string args ) ( Gebruiker tom; tom.name = "Tom"; tom.age = 34; tom.DisplayInfo(); Console.ReadKey(); ) ) )

In dit geval wordt een tom-object gemaakt. Het stelt de waarden van globale variabelen in en geeft er vervolgens informatie over weer.

Constructeurs van constructies

Net als een klasse kan een structuur constructors definiëren. Maar in tegenstelling tot een klasse hoeven we geen constructor aan te roepen om een ​​structuurobject te maken:

Gebruiker tom;

Als we echter op deze manier een structuurobject maken, moeten we alle velden (globale variabelen) van de structuur initialiseren voordat we hun waarden verkrijgen of voordat we de methoden van de structuur aanroepen. Dat wil zeggen dat we in het volgende geval bijvoorbeeld een foutmelding krijgen, omdat velden en methoden worden geopend voordat er initiële waarden aan worden toegewezen:

Gebruiker tom; int x = tom.age; // Fout tom.DisplayInfo(); // Fout

We kunnen ook een standaardconstructor gebruiken om een ​​structuur te maken. Wanneer deze wordt aangeroepen, krijgen de velden van de structuur een standaardwaarde toegewezen (voor numerieke typen is dit bijvoorbeeld het getal 0):

Gebruiker tom = nieuwe gebruiker(); tom.DisplayInfo(); // Naam: Leeftijd: 0

We kunnen ook onze eigen constructors definiëren. Laten we bijvoorbeeld de gebruikersstructuur wijzigen:

Systeem gebruiken; met behulp van System.Reflection; naamruimte HelloApp ( struct User ( publieke stringnaam; public int age; public User(stringnaam, int age) ( this.name = naam; this.age = leeftijd; ) public void DisplayInfo() ( Console.WriteLine($"Name : (naam) Leeftijd: (leeftijd)"); ) ) klasse Programma ( static void Main(string args) ( Gebruiker tom = new User("Tom", 34); tom.DisplayInfo(); Gebruiker bob = new User( ); bob.DisplayInfo(); Console.ReadKey();

Het is belangrijk om te bedenken dat als we een constructor in een structuur definiëren, deze alle velden van de structuur moet initialiseren, omdat in dit geval de waarden voor de naam- en leeftijdsvariabelen worden ingesteld.

Net als bij een klasse kun je een initializer gebruiken om een ​​structuur te maken:

Gebruiker persoon = nieuwe gebruiker (naam = "Sam", leeftijd = 31);

Maar in tegenstelling tot een klasse kunt u de velden van een structuur niet rechtstreeks initialiseren wanneer u ze declareert, bijvoorbeeld als volgt:

Structure User ( public string name = "Sam"; // ! Fout public int age = 23; // ! Fout public void DisplayInfo() ( Console.WriteLine($"Name: (name) Age: (age)"); ))