Home C++ Introduction Decisions Loops Input/Output Functions Stack and Heap References Arrays Searching and Sorting Recursion Pointers Character and Strings Structures Classes Inheritance Exceptions Templatess STL Modern C++ Misc Books ----

Introduction

The structure feature is a carry over from "C". Since "C++" provides most of what "C" has it provides support for structures.
A structure can be used to group variables. As an example of declaring structures and using them.
File: s1.cpp
#include <iostream>
using namespace std ;

struct Circle
{
    double radius;
    double diameter;
    double area;
};

int main()
{
    Circle object1 ;
    object1.radius = 2.4 ;
    object1.diameter = 2 * object1.radius  ;
    cout <<  "object1.radius: " << object1.radius <<
    " object1.diameter: " << object1.diameter << endl ;

    return(0) ;
}

Output:
[amittal@hills Structures]$ ./a.out
object1.radius: 2.4 object1.diameter: 4.8
A struct object is created with the variable "object1" and then using the dot notation the variables are set. A struct's data members are public.
A structure can have a constructor similar to a class.
File: s2.cpp
#include <iostream>
using namespace std ;

struct Circle
{
    double radius;
    double diameter;
    double area;

    Circle()
    {
        cout << "Constructor" << endl ;
    }
};

int main()
{
    Circle object1 ;
    object1.radius = 2.4 ;
    object1.diameter = 2 * object1.radius  ;
    cout <<  "object1.radius: " << object1.radius << " object1.diameter: " <<
    object1.diameter << endl ;

    return(0) ;
}
The above example shows the constructor getting called and an output statement printing the structure object's parameters. We can use the Structure as a Class object . The only difference is that the a structure's data members are public by default and a class's data members are private by default.
File: s3.cpp
#include <iostream>

using namespace std ;
struct Circle
{
 double radius;
 double diameter;
 double area;
};

int main()
{
    Circle object1 ;
    object1.radius = 2.4 ;
    object1.diameter = 2 * object1.radius  ;
    Circle object2 ;
    object2.radius = 2.4 ;
    object2.diameter = 2 * object1.radius  ;
    if( object1 == object2 )
      cout << "Two objects are equal." << endl ;
    else
      cout << "Two objects are not equal." << endl ;
    return(0) ;
}
$ g++ s3.cpp
s3.cpp: In function ‘int main()’:
s3.cpp:19:21: error: no match for ‘operator==’ (operand types are ‘Circle’ and ‘Circle’)
   19 |         if( object1 == object2 )

If we try to compile the above we get a compiler error. We cannot compare 2 objects of Circle. We can compare the data members.
File: s4.cpp
#include <iostream>
using namespace std ;

struct Circle
{
    double radius;
    double diameter;
    double area;
};

int main()
{
    Circle   object1 = {2,   4,  25.12   };
    cout <<  "object1.radius: " << object1.radius <<
    " object1.diameter: " << object1.diameter << endl ;
    return(0) ;
}
Output:

[amittal@hills Structures]$ ./a.out

object1.radius: 2 object1.diameter: 4
The above example shows how we can initialize a Circle object with some numerical values.
It is possible to declare a structure without a name. We can specify the object variable right after the structure definition.
File: s5.cpp
#include <iostream>
using namespace std ;
//A single variable
//Can't create more variables

struct
{
    double radius;
    double diameter;
    double area;
}  object1 ;

int main()
{
    //  Circle object1 ;
    object1.radius = 2.4 ;
    object1.diameter = 2 * object1.radius  ;
    cout <<  "object1.radius: " << object1.radius <<
    " object1.diameter: " << object1.diameter << endl ;

    return(0) ;
}
Note that it is also possible to define classes this way. Such classes are called anonymous classes.
File: c1.cpp
#include <iostream>
using namespace std ;

//A single variable
//Can't create more variables
class
{
    public:
    double radius;
    double diameter;
    double area;
}  object1 ;

int main()
{
    //  Circle object1 ;
    object1.radius = 2.4 ;
    object1.diameter = 2 * object1.radius  ;      cout <<  "object1.radius: " << object1.radius << " object1.diameter: " << object1.diameter << endl ;   return(0) ;}
Partial Initialization
We do not have to initialize a structure object with all the values.

File: s6.cpp
#include <iostream>
using namespace std ;

struct Circle
{
    double radius;
    double diameter;
    double area;
};

int main()
{
    Circle   object1 = {2  };
    cout <<  "object1.radius: " << object1.radius <<
    " object1.diameter: " << object1.diameter << endl ;

    return(0) ;
}
Output:
[amittal@hills Structures]$ ./a.out
object1.radius: 2 object1.diameter: 0
In the above case the other data variables take on their default values which in this case is 0.

Arrays of Structures


File: s7.cpp
#include <iostream>
using namespace std ;
/* Arrays of objects*/
struct Circle
{
    double radius;
    double diameter;
    double area;
};

int main()
{
    Circle   circleArray[2]  ;
    circleArray[0].radius  = 2 ;
    circleArray[0].diameter  = 4  ;
    circleArray[1].radius  = 3 ;
    circleArray[1].diameter  = 6  ;
    cout <<  "circleArray[0].radius: " << circleArray[0].radius <<
    " circleArray[0].diameter: " << circleArray[0].diameter <<
    endl ;
    cout <<  "circleArray[1].radius: " << circleArray[1].radius <<
    " circleArray[1].diameter: " << circleArray[1].diameter <<
    endl ;
    return(0) ;
}
Output:
[amittal@hills Structures]$ ./a.out
circleArray[0].radius: 2 circleArray[0].diameter: 4
Initialization of arrays of structures.
File: s8.cpp
#include <iostream>
using namespace std ;

/* Arrays of objects*/

struct Circle
{
 double radius;
 double diameter;
 double area;
};

int main()
{
 //Initialization of array structures
 Circle   circleArray1[2] = {  { 2 , 4,  25.12 } ,
                            { 1, 2 , 3.14 }   }  ;
 return(0) ;
}

Nested Structures

We can have nested structures also as shown in this example.
File: s9.cpp
#include <iostream>
using namespace std ;

/*Nested Structure*/
struct Circle
{
    double radius;
    double diameter;
    double area;
};

struct Shape
{
    Circle circleObject ;
    int x1 ;
};

int main()
{
    Shape  shape1 ;
    shape1.circleObject.radius = 1 ;
    shape1.circleObject.diameter = 2 ;
    shape1.circleObject.area = 3.14 ;
    return(0) ;
}

Structures as arguments


File: s10.cpp
#include <iostream>
using namespace std ;

/*Passing Structure objects as arguments*/
struct Circle
{
    double radius  ;
    double diameter  ;
    double area  ;
};
Circle  fillCircle( Circle object1 )
{
    Circle object2 ;
    object2.radius = object1.radius ;
    object2.diameter = object1.diameter ;
    object2.area = object1.area ;
    return object2 ;
}

Circle&  fillCircle1( Circle object1 )
{
    Circle object2 ;
    object2.radius = object1.radius ;
    object2.diameter = object1.diameter ;
    object2.area = object1.area ;
    return object2 ;
}
int main()
{
    Circle object1  ;
    Circle object2  = fillCircle1(  object1  ) ;
    Circle object3  = fillCircle(  object1  ) ;
    return(0) ;
}

The above example shows how structure objects can be passed to a function and returned from a function. The "fillCircle1" function has a mistake. It is returning a reference to a local object that gets destroyed when the function "fillCircle1" ends. We should either not return a reference and in that case a temporary object of type Circle will be returned or a reference to a global object that does not get destroyed. Compiling the above code produces a warning:
$ g++ s10.cpp
s10.cpp: In function ‘Circle& fillCircle1(Circle)’:
s10.cpp:26:16: warning: reference to local variable ‘object2’
returned [-Wreturn-local-addr]
   26 |         return object2 ;

Pointers to structures


File: s11.cpp
#include <iostream>
using namespace std ;
struct Circle
{
    double radius  ;
    double diameter  ;
    double area  ;
};

int main()
{
    Circle object1  ;
    Circle* ptrObject1  ;
    Circle* ptrObject2  ;
    object1.radius = 2 ;
    ptrObject1 = &object1 ;
    ptrObject2 = new Circle() ;
    cout << ptrObject1->radius   << " : " <<
    ptrObject2->radius  << endl ;
    return(0) ;
}
Output:
[amittal@hills Structures]$ g++ s11.cpp
[amittal@hills Structures]$ ./a.exe
2 : 0
We can have pointers to structures. The notation for accessing the data members for a pointer is the symbol "->" or useing "*" .
File: s12.cpp
#include <iostream>
using namespace std ;
/*Passing Structure objects as arguments*/

struct Circle
{
    double radius  ;
    double diameter  ;
    double area  ;
};

int main()
{
    Circle object1  ;
    Circle* ptrObject1  ;
    Circle* ptrObject2  ;
    object1.radius = 2 ;
    ptrObject1 = &object1 ;
    ptrObject2 = new Circle() ;
    cout << ptrObject1->radius   << " : " <<  ptrObject2->radius  <<
    endl ;
    ptrObject2->radius = 10 ;
    cout <<  (*ptrObject2).radius   << endl ;
    return(0) ;
}

Output:
[amittal@hills Structures]$ ./a.exe
2 : 0
10
The above example shows the syntax:
cout << (*ptrObject2).radius << endl ;
This is another way of accessing the data member for a pointer. The notation (*ptrObject2) will give us the object Circle and we can access the data member in the regular way of using the dot symbol "." .

Unions

A union is like a structure except that all the data members occupy the same location in RAM.
File: s13.cpp
#include <iostream>
using namespace std ;

//-----------------------------------

union test
{
    char ch ;
    int x1 ;
};
//-----------------------------------
int main()
{
    test unionObject ;
    unionObject.x1 = 32771 ;
    cout <<  unionObject.x1 << " : " << (int) unionObject.ch  <<
    endl ;
    return(0) ;
}
//-----------------------------------
$ g++ s13.cpp ; ./a.exe
32771 : 3
The union "test" contains 2 data member variables "ch" and "x1".
In RAM the union will look like:

 RAM
 ---------
 ch x1                 unionObject

Byte1
Byte2
Byte3
Byte4

The amount of memory located is for the largest data variable in the union. Our union "test" has 2 data variables: "x1" and "ch" . An int occupies 4 bytes and a character occupies 1 byte so the memory allocated is 4 bytes. Now what sets Union apart is that both "ch" and "x1" share the same memory ! Both start from Byte1. Of course the character ch will only occupy "Byte1" and the int "x1" will occupy all the4 bytes. Let's assume our CPU is Intel which it is on the machine where this code was compiled and thus the integer is stored from lowest byte to highest byte.
We are storing the number 32771. Let's see what this number looks like in 4 bytes.
In hexadecimal:
00  00  80   03
When the bytes are arranged in RAM they show up as:
03
80
00
00

We can see that the byte value of 3 is stored in Byte1 .
  cout <<  unionObject.x1 << " : " << (int) unionObject.ch  << endl ;
We can see from the output that the value of "unionObject.ch" equals 3 .

Exercises

1) How much space is allocated for the below union.
Confirm that by using the "sizeof" function.
File: ex1.cpp
#include <stdio.h>

union empAdd 
{
char *ename;
char stname[20];
int pincode;
};

int main()
{


 return 0 ; 
}
2)
File: ex2.cpp
#include <iostream>
#include <string>
#include <iomanip>
using namespace std;

struct Employee
 {
   int empNumber; // Employee number
   double hours; // Hours worked
   double payRate; // Hourly payRate
 };

 int main()
 {
    Employee emp1 = { 1, 10  , 5   }  ;
    // Create a second employee object and initialize it with emp2 with id 2
    //  hours 20 and payrate 6
    //Print pay of emp1 and pay of emp2. Pay is hours * payRate

 }