What is an Array of Objects?
An array of objects is a collection of multiple objects of the same class, stored in contiguous memory locations. Just like arrays of primitive data types (int, char, etc.), C++ allows you to create arrays where each element is an object of a class.
Declaring an Array of Objects
The basic syntax for declaring an array of objects is:
ClassName arrayName[size];
Where:
ClassNameis the name of the classarrayNameis the name you want to give to the arraysizeis the number of objects in the array
Examples of Declaring Object Arrays
Simple Example
class Student {
private:
int rollNumber;
string name;
public:
// Member functions
void setData(int roll, string n) {
rollNumber = roll;
name = n;
}
void displayData() {
cout << "Roll Number: " << rollNumber << endl;
cout << "Name: " << name << endl;
}
};
int main() {
// Creating an array of 5 Student objects
Student students[5];
// Setting data for each student
students[0].setData(101, "John");
students[1].setData(102, "Alice");
students[2].setData(103, "Bob");
students[3].setData(104, "Emma");
students[4].setData(105, "David");
// Displaying data for each student
for (int i = 0; i < 5; i++) {
cout << "Student " << i+1 << " details:" << endl;
students[i].displayData();
cout << endl;
}
return 0;
}
Initialization of an Array of Objects
There are several ways to initialize an array of objects:
1. Using Default Constructor
If the class has a default constructor (a constructor that takes no arguments), the array elements are initialized using it:
class Point {
private:
int x, y;
public:
// Default constructor
Point() {
x = 0;
y = 0;
cout << "Default constructor called" << endl;
}
void display() {
cout << "Point(" << x << ", " << y << ")" << endl;
}
};
int main() {
// This will call the default constructor for each element
Point points[3]; // Creates 3 points, all initialized to (0,0)
// Display all points
for (int i = 0; i < 3; i++) {
points[i].display();
}
return 0;
}
2. Using Parameterized Constructor
For arrays of objects where the class has a parameterized constructor, you can initialize each element using an initializer list (C++11 and later):
class Rectangle {
private:
double length;
double width;
public:
// Parameterized constructor
Rectangle(double l = 0, double w = 0) {
length = l;
width = w;
}
double area() {
return length * width;
}
void display() {
cout << "Rectangle: " << length << " x " << width;
cout << ", Area: " << area() << endl;
}
};
int main() {
// Initialize array with different values using initializer list
Rectangle rectangles[3] = {
Rectangle(5, 3), // Rectangle with length=5, width=3
Rectangle(4, 4), // Rectangle with length=4, width=4
Rectangle(7, 2) // Rectangle with length=7, width=2
};
// Display all rectangles
for (int i = 0; i < 3; i++) {
rectangles[i].display();
}
return 0;
}
3. Initialization After Declaration
You can also initialize objects after declaration by calling methods or using operators:
class Complex {
private:
double real;
double imag;
public:
// Default constructor
Complex() {
real = 0;
imag = 0;
}
// Set values
void set(double r, double i) {
real = r;
imag = i;
}
void display() {
cout << real;
if (imag >= 0) {
cout << " + " << imag << "i" << endl;
} else {
cout << " - " << -imag << "i" << endl;
}
}
};
int main() {
// Declare array of 3 Complex objects
Complex numbers[3];
// Initialize each object after declaration
numbers[0].set(2.5, 3.7);
numbers[1].set(1.1, -4.2);
numbers[2].set(7.0, 0);
// Display all complex numbers
for (int i = 0; i < 3; i++) {
numbers[i].display();
}
return 0;
}
Memory Allocation in an Array of Objects
When you create an array of objects, memory is allocated contiguously for all objects in the array. The total memory allocated is:
Total memory = Size of one object × Number of objects in the array
Each element in the array is a complete object with its own copy of data members (but they share the same member functions).
Accessing Elements in an Array of Objects
You can access individual objects in the array using array indexing, and then access their members using the dot operator:
// Accessing data members
students[2].rollNumber = 103; // Directly accessing (if public)
// Accessing member functions
students[2].setData(103, "Bob"); // Using member function
students[2].displayData(); // Calling display function
Loop Processing with an Array of Objects
Arrays of objects are often processed using loops:
For Loop
// Processing all elements with a for loop
for (int i = 0; i < size; i++) {
students[i].displayData();
}
Range-Based For Loop (C++11 and later)
// Using range-based for loop (C++11 and later)
for (Student& stud : students) {
stud.displayData();
}
Dynamic Arrays of Objects
You can also create arrays of objects dynamically using the new operator:
// Creating a dynamic array of 10 Student objects
Student* dynamicStudents = new Student[10];
// Using the dynamic array
dynamicStudents[0].setData(201, "Michael");
dynamicStudents[1].setData(202, "Sarah");
// Don't forget to delete the array when done
delete[] dynamicStudents;
Two-Dimensional Arrays of Objects
You can also create two-dimensional arrays of objects:
// 2D array: 3 rows × 2 columns of Point objects
Point grid[3][2];
// Access elements
grid[0][0].setCoordinates(1, 1);
grid[2][1].display();
// Process all elements with nested loops
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 2; j++) {
grid[i][j].display();
}
}
Advanced Example: Array of Objects with Constructor Parameters
Here’s a more complete example showing an array of objects with a parameterized constructor:
#include <iostream>
#include <string>
using namespace std;
class Book {
private:
string title;
string author;
int pages;
double price;
public:
// Default constructor
Book() {
title = "Unknown";
author = "Unknown";
pages = 0;
price = 0.0;
}
// Parameterized constructor
Book(string t, string a, int p, double pr) {
title = t;
author = a;
pages = p;
price = pr;
}
// Display book details
void display() {
cout << "Title: " << title << endl;
cout << "Author: " << author << endl;
cout << "Pages: " << pages << endl;
cout << "Price: $" << price << endl;
}
// Getter for price
double getPrice() {
return price;
}
};
int main() {
// Array of 5 Book objects with initialization
Book library[5] = {
Book("The Great Gatsby", "F. Scott Fitzgerald", 180, 12.99),
Book("To Kill a Mockingbird", "Harper Lee", 281, 14.50),
Book("1984", "George Orwell", 328, 10.75),
Book("Pride and Prejudice", "Jane Austen", 432, 9.99),
Book("The Hobbit", "J.R.R. Tolkien", 366, 15.25)
};
// Display all books
cout << "Library Catalog:" << endl;
cout << "================" << endl;
for (int i = 0; i < 5; i++) {
cout << "Book " << (i+1) << ":" << endl;
library[i].display();
cout << endl;
}
// Find the most expensive book
int mostExpensiveIndex = 0;
for (int i = 1; i < 5; i++) {
if (library[i].getPrice() > library[mostExpensiveIndex].getPrice()) {
mostExpensiveIndex = i;
}
}
cout << "The most expensive book is:" << endl;
library[mostExpensiveIndex].display();
return 0;
}
Practical Applications of Arrays of Objects
Arrays of objects are useful in many real-world applications:
- School Management Systems: Array of Student objects
- Library Systems: Array of Book objects
- Banking Applications: Array of Account objects
- Game Development: Array of Character, Enemy, or Item objects
- Inventory Systems: Array of Product objects
- Weather Data: Array of WeatherReading objects
Common Errors and Pitfalls
- Forgetting Default Constructor: If you declare an array without initialization and your class has no default constructor, you’ll get a compilation error.
- Memory Leaks: Not deleting dynamically allocated arrays.
- Out-of-Bounds Access: Accessing elements beyond the array size.
- Shallow Copying: Be careful with classes that manage resources (pointers) when creating arrays, as default copying might lead to problems.
Best Practices
- Use Standard Containers: For most applications, consider using
std::vectororstd::arrayinstead of raw arrays for better safety and flexibility. - Prefer Stack Allocation: When the array size is known and small, prefer stack allocation over dynamic allocation.
- Initialize All Elements: Make sure all array elements are properly initialized.
- Range Checking: Always check array bounds before accessing elements.
- Consider Object Size: Be cautious with arrays of large objects, as they can consume a lot of memory.
Summary
Arrays of objects in C++ allow you to create collections of related objects of the same class. They combine the efficiency of arrays with the power of object-oriented programming. You can initialize them using constructors, process them with loops, and access individual objects and their members using array indexing and the dot operator. For more dynamic scenarios, consider using standard library containers like std::vector which offer more flexibility and safety than raw arrays.