1
2
3
4
5
6
| char strName[20]; int nBirthYear; int nBirthMonth; int nBirthDay; int nHeight; // in inches int nWeight; // in pounds |
Fortunately, C++ allows us to create our own user-defined aggregate data types. An aggregate data type is a data type that groups multiple individual variables together. One of the simplest aggregate data type is the struct. A struct (short for structure) allows us to group variables of mixed data types together into a single unit.
Because structs are user-defined, we first have to tell the compiler what our struct looks like before we can begin using it. To do this, we declare our struct using the struct keyword. Here is an example of a struct declaration:
1
2
3
4
5
6
| struct Employee { int nID; int nAge; float fWage; }; |
In order to use the Employee struct, we simply declare a variable of type Employee:
1
| Employee sJoe; |
To find out the exact size of Employee, we can use the sizeof operator:
1
| cout << "The size of Employee is " << sizeof (Employee); |
The size of Employee is 12
.When we declare a variable such as
Employee sJoe
, sJoe
refers to the entire struct (which contains the member variables). In
order to access the individual members, we use the member selection operator
(which is a period). As with normal variables, struct member variables
are not initialized, and will typically contain junk. We must
initialize them manually. Here is an example of using the member
selection operator to initialize each member variable:
1
2
3
4
| Employee sJoe; sJoe.nID= 14; // initialize nID within sJoe sJoe.nAge = 32; // initialize nAge within sJoe sJoe.fWage = 24.15; // initialize fWage within sJoe |
1
2
3
4
5
6
7
8
9
| Employee sJoe; // create an Employee struct for Joe sJoe.nID = 14; sJoe.nAge = 32; sJoe.fWage = 24.15; Employee sFrank; // create an Employee struct for Frank sFrank.nID = 15; sFrank.nAge = 28; sFrank.fWage = 18.27; |
Struct member variables act just like normal variables, so it is possible to do normal operations on them:
1
2
3
4
5
6
7
8
9
10
| int nTotalAge = sJoe.nAge + sFrank.nAge; if (sJoe.fWage > sFrank.fWage) cout << "Joe makes more than Frank" << endl; // Frank got a promotion sFrank.fWage += 2.50; // Today is Joe's birthday sJoe.nAge++; |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
| #include <iostream> void PrintInformation(Employee sEmployee) { using namespace std; cout << "ID: " << sEmployee.nID << endl; cout << "Age: " << sEmployee.nAge << endl; cout << "Wage: " << sEmployee.fWage << endl << endl; } int main() { Employee sJoe; // create an Employee struct for Joe sJoe.nID = 14; sJoe.nAge = 32; sJoe.fWage = 24.15; Employee sFrank; // create an Employee struct for Frank sFrank.nID = 15; sFrank.nAge = 28; sFrank.fWage = 18.27; // Print Joe's information PrintInformation(sJoe); // Print Frank's information PrintInformation(sFrank); return 0; } |
PrintInformation() uses the Employee struct passed to it to print out employee information to the screen. The above program outputs:
ID: 14 Age: 32 Wage: 24.15 ID: 15 Age: 28 Wage: 18.27Structs can contain other structs. For example:
1
2
3
4
5
6
7
| struct Company { Employee sCEO; // Employee is a struct within the Company struct int nNumberOfEmployees; }; Company sMyCompany; |
sMyCompany.sCEO.fWage;
This selects the sCEO member from sMyCompany, and then selects the fWage member from within sCEO.
Initializer lists
Initializing structs member by member is a little cumbersome, so C++ supports a faster way to initialize structs using an initializer list. This allows you to initialize some or all the members of a struct at declaration time.
1
2
3
4
5
6
7
8
| struct Employee { int nID; int nAge; float fWage; }; Employee sJoe = {1, 42, 60000.0f}; // nID=1, nAge=42, fWage=60000.0 |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| struct Employee { int nID; int nAge; float fWage; }; struct Company { Employee sCEO; // Employee is a struct within the Company struct int nNumberOfEmployees; }; Company sCo1 = {{1, 42, 60000.0f}, 5}; |
The “m_” Hungarian Notation prefix for members is typically not used for structs, even though structs contain members. This is (in part) because all variables in a struct are members! Consequently, labeling them with a “m_” prefix is somewhat redundant.
It is common to declare structs in a header file, so they can be accessed by multiple source files.
The class aggregate data type builds on top of the functionality offered by structs. Classes are at the heart of C++ object-oriented programming. Understanding structs is the first step towards object-oriented programming!
Sign up here with your email
ConversionConversion EmoticonEmoticon