C++ Classes and Objects

If you want to write powerful C++ programs, you can do this by understanding C++ classes and objects. They help you organize your code. They also make your programs easier to manage.

C++ Classes and Objects

This guide shows you how to use C++ classes and objects. You will learn what they are. You will also see how they work with clear examples.

What is a C++ Class?

A C++ class is a user-defined data type that serves as a template for creating objects. It defines the structure and behavior of the objects by specifying the data (variables) and functions (methods) that operate on that data.

You use classes to describe properties and actions. For example, a “Car” class might have properties like “color” and “speed.” It might also have actions like “start” and “stop.”

Here’s why classes matter:

  • Code Organization: Classes group related data and functions together. This makes your code neat.
  • Reusability: You write a class once. Then you can use it many times to create different objects.
  • Data Protection: Classes help protect your data from unwanted changes.

Defining a Class

You define a class using the class keyword. You give it a name. Then you put its members inside curly braces {}.

Here is a simple example of a Car class:

class Car {
public:
    // Properties (data members)
    std::string color;
    int speed;

    // Actions (member functions)
    void start() {
        // Code to start the car
    }

    void stop() {
        // Code to stop the car
    }
};

In this example, Car is the name of the class. color and speed are data members which store information. start() and stop() are member functions which perform actions. public: means you can access these members from outside the class.

What is a C++ Object?

A C++ object is a real instance of a class. If a class is a blueprint, an object is the actual house built from that blueprint. You create many objects from one class blueprint. Each object has its own set of data.

For example, from the Car blueprint, you can create:

  • A red car with a speed of 100 km/h.
  • A blue car with a speed of 120 km/h.

Each of these is a Car object. They both come from the Car class.

Creating an Object

You create an object by declaring a variable of the class type.

Here’s how you create Car objects:

#include <iostream> // Needed for output
#include <string>   // Needed for string type

class Car {
public:
    std::string color;
    int speed;

    void start() {
        std::cout << "The " << color << " car is starting." << std::endl;
    }

    void stop() {
        std::cout << "The " << color << " car is stopping." << std::endl;
    }
};

int main() {
    Car car1; // Create an object named car1
    Car car2; // Create another object named car2

    return 0;
}

In main(), car1 and car2 are objects of the Car class. They are separate cars.

Accessing Class Members

You access data members and member functions of an object using the dot (.) operator.

Here’s how you work with car1 and car2:

#include <iostream>
#include <string>

class Car {
public:
    std::string color;
    int speed;

    void start() {
        std::cout << "The " << color << " car is starting." << std::endl;
    }

    void stop() {
        std::cout << "The " << color << " car is stopping." << std::endl;
    }
};

int main() {
    Car car1; // Create car1 object
    car1.color = "Red"; // Set car1's color
    car1.speed = 100;   // Set car1's speed

    Car car2; // Create car2 object
    car2.color = "Blue"; // Set car2's color
    car2.speed = 120;    // Set car2's speed

    std::cout << "Car 1: Color = " << car1.color << ", Speed = " << car1.speed << std::endl;
    car1.start(); // Call start() function for car1

    std::cout << "Car 2: Color = " << car2.color << ", Speed = " << car2.speed << std::endl;
    car2.stop(); // Call stop() function for car2

    return 0;
}

When you run this code, you see output that shows each car’s details and actions.

Car 1: Color = Red, Speed = 100
The Red car is starting.
Car 2: Color = Blue, Speed = 120
The Blue car is stopping.

Public and Private Access Specifiers

Classes use access specifiers to control how you access their members.

  • public: You can access public members from anywhere in the program. You saw this in the Car class example.
  • private: You can only access private members from inside the class itself. You cannot access them directly from outside the class. This protects data.

Here’s an example with private members:

#include <iostream>
#include <string>

class Dog {
private:
    std::string name; // Private data member
    int age;          // Private data member

public:
    // Public functions to set and get private data
    void setName(std::string n) {
        name = n;
    }

    std::string getName() {
        return name;
    }

    void setAge(int a) {
        if (a > 0) { // Add a check for valid age
            age = a;
        } else {
            std::cout << "Age cannot be zero or negative." << std::endl;
        }
    }

    int getAge() {
        return age;
    }

    void bark() {
        std::cout << name << " barks loudly!" << std::endl;
    }
};

int main() {
    Dog myDog;

    // myDog.name = "Buddy"; // This would cause an error! 'name' is private.

    myDog.setName("Buddy"); // Use public function to set name
    myDog.setAge(3);        // Use public function to set age

    std::cout << "My dog's name is " << myDog.getName() << std::endl;
    std::cout << "My dog's age is " << myDog.getAge() << std::endl;
    myDog.bark();

    myDog.setAge(-1); // This will show an error message from setAge

    return 0;
}

In the Dog class, name and age are private. You cannot change them directly from main(). Functions like setName() and setAge() are public. They provide a controlled way to access and modify private data. This setup helps keep data safe.

My dog's name is Buddy
My dog's age is 3
Buddy barks loudly!
Age cannot be zero or negative.

Constructors

A constructor is a special member function that is automatically called when an object is created. It is used to initialize the object’s properties by setting initial values for its data members.

Constructors have the same name as the class. They do not have a return type, not even void.

Parameterized Constructors

Here’s a Rectangle class with a constructor that takes parameters:

#include <iostream>

class Rectangle {
private:
    double length;
    double width;

public:
    // Constructor
    Rectangle(double l, double w) {
        length = l;
        width = w;
        std::cout << "A rectangle object is created." << std::endl;
    }

    double calculateArea() {
        return length * width;
    }
};

int main() {
    // This calls the constructor with 5.0 and 3.0
    Rectangle rect1(5.0, 3.0);
    std::cout << "Area of rect1: " << rect1.calculateArea() << std::endl;

    // This calls the constructor with 7.0 and 4.0
    Rectangle rect2(7.0, 4.0);
    std::cout << "Area of rect2: " << rect2.calculateArea() << std::endl;

    return 0;
}

When you create rect1 and rect2, the constructor runs. It sets their length and width.

A rectangle object is created.
Area of rect1: 15
A rectangle object is created.
Area of rect2: 28

Default Constructors

You can also have a default constructor. This constructor takes no arguments.

#include <iostream>

class Box {
private:
    double height;
    double width;

public:
    // Default Constructor
    Box() {
        height = 1.0; // Default height
        width = 1.0;  // Default width
        std::cout << "Default Box created." << std::endl;
    }

    // Parameterized Constructor
    Box(double h, double w) {
        height = h;
        width = w;
        std::cout << "Box with specific dimensions created." << std::endl;
    }

    double getArea() {
        return height * width;
    }
};

int main() {
    Box box1; // Calls the default constructor
    std::cout << "Area of box1: " << box1.getArea() << std::endl;

    Box box2(5.0, 6.0); // Calls the parameterized constructor
    std::cout << "Area of box2: " << box2.getArea() << std::endl;

    return 0;
}
Default Box created.
Area of box1: 1
Box with specific dimensions created.
Area of box2: 30

Destructors

A destructor is another special member function. It runs automatically when an object is destroyed. This happens when an object goes out of scope. You use destructors to release resources. For example, you might close files or free up memory.

Destructors have the same name as the class, but with a tilde ~ in front. They do not take any arguments. They also do not have a return type.

#include <iostream>
#include <string>

class ResourceHandler {
public:
    std::string resourceName;

    ResourceHandler(std::string name) {
        resourceName = name;
        std::cout << "Resource " << resourceName << " is acquired." << std::endl;
    }

    // Destructor
    ~ResourceHandler() {
        std::cout << "Resource " << resourceName << " is released." << std::endl;
    }

    void doWork() {
        std::cout << "Working with " << resourceName << "." << std::endl;
    }
};

int main() {
    { // Start of a new scope
        ResourceHandler myFile("MyImportantFile.txt");
        myFile.doWork();
    } // myFile object is destroyed here, destructor is called

    std::cout << "Program continues after resource is released." << std::endl;

    return 0;
}

When myFile goes out of scope at the end of the block, its destructor ~ResourceHandler() runs. It prints a message showing the resource is released.

Resource MyImportantFile.txt is acquired.
Working with MyImportantFile.txt.
Resource MyImportantFile.txt is released.
Program continues after resource is released.

Member Functions Outside the Class Definition

You can define member functions outside the class definition. You do this using the scope resolution operator (::). This helps keep class definitions clean, especially for large functions.

Here’s an example:

#include <iostream>
#include <string>

class Student {
public:
    std::string name;
    int studentId;

    void displayInfo(); // Declaration of the function
};

// Definition of the function outside the class
void Student::displayInfo() {
    std::cout << "Student Name: " << name << std::endl;
    std::cout << "Student ID: " << studentId << std::endl;
}

int main() {
    Student s1;
    s1.name = "Alice";
    s1.studentId = 101;
    s1.displayInfo(); // Call the member function

    Student s2;
    s2.name = "Bob";
    s2.studentId = 102;
    s2.displayInfo();

    return 0;
}

You use Student:: to tell the compiler that displayInfo is part of the Student class.

Student Name: Alice
Student ID: 101
Student Name: Bob
Student ID: 102

Object-Oriented Programming (OOP) Concepts

Classes and objects are fundamental to Object-Oriented Programming (OOP). OOP is a way to design programs using objects. Besides encapsulation (grouping data and functions) and data hiding (using private), two other core OOP concepts are:

  • Inheritance: This lets a new class (derived class) take on properties and behaviors from an existing class (base class). Think of it like a child inheriting traits from a parent. This promotes code reuse.
  • Polymorphism: This means “many forms.” It allows you to use one interface to represent different underlying forms. For example, a “Shape” class might have a draw() method, and different shapes (Circle, Square) would implement draw() in their own way.

While this guide focuses on the basics, understanding these concepts helps you write more flexible and powerful C++ programs.

Putting It All Together

Let’s combine what you learned into a complete program. This program creates a Book class. It has properties like title and author. It also has functions to display book details.

#include <iostream>
#include <string>

class Book {
private:
    std::string title;
    std::string author;
    int publicationYear;

public:
    // Constructor to initialize book properties
    Book(std::string t, std::string a, int year) {
        title = t;
        author = a;
        publicationYear = year;
        std::cout << "Book '" << title << "' created." << std::endl;
    }

    // Destructor
    ~Book() {
        std::cout << "Book '" << title << "' destroyed." << std::endl;
    }

    // Public function to display book information
    void displayBookInfo() {
        std::cout << "Title: " << title << std::endl;
        std::cout << "Author: " << author << std::endl;
        std::cout << "Publication Year: " << publicationYear << std::endl;
    }

    // Getter function for title
    std::string getTitle() {
        return title;
    }
};

int main() {
    std::cout << "Creating books..." << std::endl;

    // Create the first book object
    Book book1("The Hobbit", "J.R.R. Tolkien", 1937);
    book1.displayBookInfo();
    std::cout << std::endl;

    // Create the second book object
    Book book2("1984", "George Orwell", 1949);
    book2.displayBookInfo();
    std::cout << std::endl;

    // Access title using getter
    std::cout << "The title of book1 is: " << book1.getTitle() << std::endl;
    std::cout << std::endl;

    std::cout << "Books created. Program continues." << std::endl;

    return 0; // Objects book1 and book2 are destroyed here
}

This program shows:

  • A Book class with private data members for data protection.
  • A constructor to set initial values when you create a Book object.
  • A destructor that runs when Book objects are destroyed.
  • Public member functions to interact with the object’s data.
Creating books...
Book 'The Hobbit' created.
Title: The Hobbit
Author: J.R.R. Tolkien
Publication Year: 1937

Book '1984' created.
Title: 1984
Author: George Orwell
Publication Year: 1949

The title of book1 is: The Hobbit

Books created. Program continues.
Book '1984' destroyed.
Book 'The Hobbit' destroyed.

Next Steps

C++ classes and objects help you write organized and efficient code. A class is a blueprint, and an object is a specific instance. You use access specifiers to control data access. Constructors initialize objects, and destructors clean up resources.

Now that you have a solid foundation, try these challenges:

  • Modify the Dog class: Add a new private data member like breed. Then create public setBreed() and getBreed() methods.
  • Create your own class: Design a BankAccount class with private members for accountNumber and balance. Add public methods to deposit and withdraw money.
  • Experiment with constructors: Add another constructor to the Book class that only takes the title and sets the author to “Unknown” and publication year to 0 by default.

Experimenting with code is a great way to solidify your understanding. What will you build first?

Avatar photo
Great Learning Editorial Team
The Great Learning Editorial Staff includes a dynamic team of subject matter experts, instructors, and education professionals who combine their deep industry knowledge with innovative teaching methods. Their mission is to provide learners with the skills and insights needed to excel in their careers, whether through upskilling, reskilling, or transitioning into new fields.

Academy Pro Subscription

Grab 50% off
on Top Courses - Free Trial Available

×
Scroll to Top