Section 3.5 Structures | ||
where model_name is a name for the model of the structure type and the optional parameter object_name is a valid identifier (or identifiers) for structure object instantiations. Within curly brackets { } they are the types and their sub-identifiers corresponding to the elements that compose the structure.struct model_name { type1 element1; type2 element2; type3 element3; . . } object_name;
If the structure definition includes the parameter model_name (optional), that parameter becomes a valid type name equivalent to the structure. For example:
We have first defined the structure model products with two fields: name and price, each of a different type. We have then used the name of the structure type (products) to declare three objects of that type: apple, orange and melon.struct products { char name [30]; float price; } ; products apple; products orange, melon;
Once declared, products has become a new valid type name like the fundamental ones int, char or short and we are able to declare objects (variables) of that type.
The optional field object_name that can go at the end of the structure declaration serves to directly declare objects of the structure type. For example, we can also declare the structure objects apple, orange and melon this way:
Moreover, in cases like the last one in which we took advantage of the declaration of the structure model to declare objects of it, the parameter model_name (in this case products) becomes optional. Although if model_name is not included it will not be possible to declare more objects of this same model later.struct products { char name [30]; float price; } apple, orange, melon;
It is important to clearly differentiate between what is a structure model, and what is a structure object. Using the terms we used with variables, the model is the type, and the object is the variable. We can instantiate many objects (variables) from a single model (type).
Once we have declared our three objects of a determined structure model (apple, orange and melon) we can operate with the fields that form them. To do that we have to use a point (.) inserted between the object name and the field name. For example, we could operate with any of these elements as if they were standard variables of their respective types:
apple.nameeach one being of its corresponding data type: apple.name, orange.name and melon.name are of type char[30], and apple.price, orange.price and melon.price are of type float.
apple.price
orange.name
orange.price
melon.name
melon.price
We are going to leave apples, oranges and melons and go with an example about movies:
// example about structures #include <iostream.h> #include <string.h> #include <stdlib.h> struct movies_t { char title [50]; int year; } mine, yours; void printmovie (movies_t movie); int main () { char buffer [50]; strcpy (mine.title, "2001 A Space Odyssey"); mine.year = 1968; cout << "Enter title: "; cin.getline (yours.title,50); cout << "Enter year: "; cin.getline (buffer,50); yours.year = atoi (buffer); cout << "My favourite movie is:\n "; printmovie (mine); cout << "And yours:\n "; printmovie (yours); return 0; } void printmovie (movies_t movie) { cout << movie.title; cout << " (" << movie.year << ")\n"; } |
Enter title: Alien Enter year: 1979 My favourite movie is: 2001 A Space Odyssey (1968) And yours: Alien (1979) |
The example shows how we can use the elements of a structure and the structure itself as normal variables. For example, yours.year is a valid variable of type int, and mine.title is a valid array of 50 chars.
Notice that mine and yours are also treated as valid variables of type movies_t when being passed to the function printmovie(). Therefore, one of the most important advantages of structures is that we can refer either to their elements individually or to the entire structure as a block.
Structures are a feature used very often to build data bases, specially if we consider the possibility of building arrays of them.
// array of structures #include <iostream.h> #include <stdlib.h> #define N_MOVIES 5 struct movies_t { char title [50]; int year; } films [N_MOVIES]; void printmovie (movies_t movie); int main () { char buffer [50]; int n; for (n=0; n<N_MOVIES; n++) { cout << "Enter title: "; cin.getline (films[n].title,50); cout << "Enter year: "; cin.getline (buffer,50); films[n].year = atoi (buffer); } cout << "\nYou have entered these movies:\n"; for (n=0; n<N_MOVIES; n++) printmovie (films[n]); return 0; } void printmovie (movies_t movie) { cout << movie.title; cout << " (" << movie.year << ")\n"; } |
Enter title: Alien Enter year: 1979 Enter title: Blade Runner Enter year: 1982 Enter title: Matrix Enter year: 1999 Enter title: Rear Window Enter year: 1954 Enter title: Taxi Driver Enter year: 1975 You have entered these movies: Alien (1979) Blade Runner (1982) Matrix (1999) Rear Window (1954) Taxi Driver (1975) |
Here amovie is an object of struct type movies_t and pmovie is a pointer to point to objects of struct type movies_t. So, the following, as with fundamental types, would also be valid:struct movies_t { char title [50]; int year; }; movies_t amovie; movies_t * pmovie;
pmovie = &amovie;Ok, we will now go with another example, that will serve to introduce a new operator:
// pointers to structures #include <iostream.h> #include <stdlib.h> struct movies_t { char title [50]; int year; }; int main () { char buffer[50]; movies_t amovie; movies_t * pmovie; pmovie = & amovie; cout << "Enter title: "; cin.getline (pmovie->title,50); cout << "Enter year: "; cin.getline (buffer,50); pmovie->year = atoi (buffer); cout << "\nYou have entered:\n"; cout << pmovie->title; cout << " (" << pmovie->year << ")\n"; return 0; } |
Enter title: Matrix Enter year: 1999 You have entered: Matrix (1999) |
The previous code includes an important introduction: operator ->. This is a reference operator that is used exclusively with pointers to structures and pointers to classes. It allows us not to have to use parenthesis on each reference to a structure member. In the example we used:
pmovie->titlethat could be translated to:
(*pmovie).titleboth expressions pmovie->title and (*pmovie).title are valid and mean that we are evaluating the element title of the structure pointed by pmovie. You must distinguish it clearly from:
*pmovie.titlethat is equivalent to
*(pmovie.title)and that would serve to evaluate the value pointed by element title of structure movies, that in this case (where title is not a pointer) it would not make much sense. The following panel summarizes possible combinations of pointers and structures:
Expression Description Equivalent pmovie.title Element title of structure pmovie pmovie->title Element title of structure pointed by pmovie (*pmovie).title *pmovie.title Value pointed by element title of structure pmovie *(pmovie.title)
Therefore, after the previous declaration we could use the following expressions:struct movies_t { char title [50]; int year; } struct friends_t { char name [50]; char email [50]; movies_t favourite_movie; } charlie, maria; friends_t * pfriends = &charlie;
charlie.name(where, by the way, the last two expressions are equivalent).
maria.favourite_movie.title
charlie.favourite_movie.year
pfriends->favourite_movie.year
The concept of structures that has been discussed in this section is the same as used in C language, nevertheless, in C++, the structure concept has been extended up to the same functionality of a class with the peculiarity that all of its elements are considered public. But you will have more details about this topic on section 4.1, Classes.
© The C++ Resources Network, 2000-2003 - All rights reserved |
Previous: 3-4. Dynamic memory |
index |
Next: 3-6. User defined data types. |