Create Classes and Objects in C++

C++C++Beginner
Practice Now

Introduction

In this lab, you will learn how to create classes and objects in C++ programming. You will define classes with private data members, implement public member functions, create constructors with different parameters, write destructors for resource cleanup, use access specifiers, implement inheritance between classes, override base class methods, create friend functions for access control, and use static members and methods. These concepts are fundamental to object-oriented programming in C++ and will provide a solid foundation for building more complex applications.


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL cpp(("`C++`")) -.-> cpp/FunctionsGroup(["`Functions`"]) cpp(("`C++`")) -.-> cpp/OOPGroup(["`OOP`"]) cpp(("`C++`")) -.-> cpp/BasicsGroup(["`Basics`"]) cpp/FunctionsGroup -.-> cpp/function_parameters("`Function Parameters`") cpp/OOPGroup -.-> cpp/classes_objects("`Classes/Objects`") cpp/OOPGroup -.-> cpp/class_methods("`Class Methods`") cpp/OOPGroup -.-> cpp/constructors("`Constructors`") cpp/OOPGroup -.-> cpp/access_specifiers("`Access Specifiers`") cpp/OOPGroup -.-> cpp/encapsulation("`Encapsulation`") cpp/OOPGroup -.-> cpp/inheritance("`Inheritance`") cpp/OOPGroup -.-> cpp/polymorphism("`Polymorphism`") cpp/BasicsGroup -.-> cpp/data_types("`Data Types`") subgraph Lab Skills cpp/function_parameters -.-> lab-446079{{"`Create Classes and Objects in C++`"}} cpp/classes_objects -.-> lab-446079{{"`Create Classes and Objects in C++`"}} cpp/class_methods -.-> lab-446079{{"`Create Classes and Objects in C++`"}} cpp/constructors -.-> lab-446079{{"`Create Classes and Objects in C++`"}} cpp/access_specifiers -.-> lab-446079{{"`Create Classes and Objects in C++`"}} cpp/encapsulation -.-> lab-446079{{"`Create Classes and Objects in C++`"}} cpp/inheritance -.-> lab-446079{{"`Create Classes and Objects in C++`"}} cpp/polymorphism -.-> lab-446079{{"`Create Classes and Objects in C++`"}} cpp/data_types -.-> lab-446079{{"`Create Classes and Objects in C++`"}} end

Define Class with Private Data Members

A class in C++ is a blueprint for creating objects. It defines a set of properties (data members) and methods (member functions) that the objects created from the class will have. Classes help in organizing code and implementing object-oriented programming principles such as encapsulation, inheritance, and polymorphism.

The basic syntax for defining a class in C++ is as follows:

class ClassName {
private:
    // Private data members
    int dataMember1;
    std::string dataMember2;

public:
    // Public member functions
    void memberFunction1();
    int memberFunction2();
};

There are three access specifiers in C++ that control the visibility and accessibility of class members:

  • private: Members declared as private are accessible only within the class.
  • public: Members declared as public are accessible from outside the class.
  • protected: Members declared as protected are accessible within the class and by derived class instances.

In this step, you'll learn how to define a class with private data members in C++. Private data members are an essential concept in object-oriented programming that helps encapsulate and protect the internal state of an object.

First, open the WebIDE and navigate to the ~/project directory. Create a new file called student.cpp:

touch ~/project/student.cpp

Open the student.cpp file in the WebIDE and add the following code to define a Student class with private data members:

#include <iostream>
#include <string>

class Student {
private:
    // Private data members
    std::string name;
    int age;
    double gpa;

public:
    // We'll add methods to interact with these private members in later steps
    void displayInfo() {
        std::cout << "Name: " << name << std::endl;
        std::cout << "Age: " << age << std::endl;
        std::cout << "GPA: " << gpa << std::endl;
    }
};

int main() {
    Student student;
    // Note: We can't directly access private members
    // student.name = "John"; // This would cause a compilation error

    student.displayInfo();
    return 0;
}

Let's break down the key concepts:

  1. Private Data Members:

    • Declared using the private: access specifier
    • Cannot be directly accessed from outside the class
    • Provide data protection and encapsulation
  2. Data Types:

    • std::string name: Stores student's name
    • int age: Stores student's age
    • double gpa: Stores student's grade point average
  3. Encapsulation:

    • Private members can only be accessed through public methods
    • Prevents direct modification of internal data

Compile the program:

g++ student.cpp -o student
./student

Example output when running the program:

Name:
Age: 0
GPA: 0

Key points:

  • Private members are hidden from outside access
  • They can only be modified through class methods
  • This helps maintain data integrity and control

Implement Public Member Functions

In this step, you'll learn how to implement public member functions in C++. Public member functions allow controlled access to private data members and provide ways to interact with class objects.

Open the student.cpp file in the WebIDE and modify the Student class to include public member functions:

#include <iostream>
#include <string>

class Student {
private:
    std::string name;
    int age;
    double gpa;

public:
    // Setter methods to modify private data members
    void setName(std::string studentName) {
        name = studentName;
    }

    void setAge(int studentAge) {
        if (studentAge > 0 && studentAge < 120) {
            age = studentAge;
        } else {
            std::cout << "Invalid age!" << std::endl;
        }
    }

    void setGPA(double studentGPA) {
        if (studentGPA >= 0.0 && studentGPA <= 4.0) {
            gpa = studentGPA;
        } else {
            std::cout << "Invalid GPA!" << std::endl;
        }
    }

    // Getter methods to access private data members
    std::string getName() {
        return name;
    }

    int getAge() {
        return age;
    }

    double getGPA() {
        return gpa;
    }

    // Display method to print student information
    void displayInfo() {
        std::cout << "Student Information:" << std::endl;
        std::cout << "Name: " << name << std::endl;
        std::cout << "Age: " << age << std::endl;
        std::cout << "GPA: " << gpa << std::endl;
    }
};

int main() {
    Student student;

    // Using public member functions to set and get data
    student.setName("Alice Johnson");
    student.setAge(20);
    student.setGPA(3.75);

    // Display student information
    student.displayInfo();

    // Demonstrate getter methods
    std::cout << "\nStudent Name: " << student.getName() << std::endl;
    std::cout << "Student Age: " << student.getAge() << std::endl;
    std::cout << "Student GPA: " << student.getGPA() << std::endl;

    return 0;
}

Compile and run the program:

g++ student.cpp -o student
./student

Example output:

Student Information:
Name: Alice Johnson
Age: 20
GPA: 3.75

Student Name: Alice Johnson
Student Age: 20
Student GPA: 3.75

Key points about public member functions:

  • Provide controlled access to private data members
  • Setters allow modification with validation
  • Getters allow reading private data
  • Help maintain encapsulation and data integrity

Create Constructors with Different Parameters

In this step, you'll learn how to create constructors with different parameters in C++. Constructors are special member functions that initialize objects when they are created.

Open the student.cpp file in the WebIDE and modify the Student class to include multiple constructors:

#include <iostream>
#include <string>

class Student {
private:
    std::string name;
    int age;
    double gpa;

public:
    // Default constructor
    Student() {
        name = "Unknown";
        age = 0;
        gpa = 0.0;
    }

    // Constructor with name parameter
    Student(std::string studentName) {
        name = studentName;
        age = 0;
        gpa = 0.0;
    }

    // Constructor with name and age parameters
    Student(std::string studentName, int studentAge) {
        name = studentName;
        age = studentAge;
        gpa = 0.0;
    }

    // Full constructor with all parameters
    Student(std::string studentName, int studentAge, double studentGPA) {
        name = studentName;
        age = studentAge;
        gpa = studentGPA;
    }

    // Display method to print student information
    void displayInfo() {
        std::cout << "Student Information:" << std::endl;
        std::cout << "Name: " << name << std::endl;
        std::cout << "Age: " << age << std::endl;
        std::cout << "GPA: " << gpa << std::endl;
    }
};

int main() {
    // Using different constructors
    Student student1;  // Default constructor
    Student student2("Alice Johnson");  // Constructor with name
    Student student3("Bob Smith", 22);  // Constructor with name and age
    Student student4("Charlie Brown", 20, 3.75);  // Full constructor

    std::cout << "Student 1:" << std::endl;
    student1.displayInfo();

    std::cout << "\nStudent 2:" << std::endl;
    student2.displayInfo();

    std::cout << "\nStudent 3:" << std::endl;
    student3.displayInfo();

    std::cout << "\nStudent 4:" << std::endl;
    student4.displayInfo();

    return 0;
}

Compile and run the program:

g++ student.cpp -o student
./student

Example output:

Student 1:
Student Information:
Name: Unknown
Age: 0
GPA: 0

Student 2:
Student Information:
Name: Alice Johnson
Age: 0
GPA: 0

Student 3:
Student Information:
Name: Bob Smith
Age: 22
GPA: 0

Student 4:
Student Information:
Name: Charlie Brown
Age: 20
GPA: 3.75

Key points about constructors:

  • Constructors have the same name as the class
  • They initialize object data members
  • Can have multiple constructors with different parameters
  • Called automatically when an object is created

Write Destructor for Resource Cleanup

In this step, you'll learn about destructors in C++, which are special member functions responsible for cleaning up resources when an object is destroyed. We'll demonstrate how to write a destructor and understand its importance in memory management.

Open the student.cpp file in the WebIDE and modify the code to include a destructor and dynamic memory allocation:

#include <iostream>
#include <string>

class Student {
private:
    std::string name;
    int age;
    double gpa;
    char* dynamicBuffer;  // Simulating dynamic memory allocation

public:
    // Constructors
    Student() {
        name = "Unknown";
        age = 0;
        gpa = 0.0;
        dynamicBuffer = new char[50];  // Allocate dynamic memory
        std::cout << "Default Constructor Called" << std::endl;
    }

    Student(std::string studentName) : name(studentName), age(0), gpa(0.0) {
        dynamicBuffer = new char[50];
        std::cout << "Parameterized Constructor Called" << std::endl;
    }

    // Destructor
    ~Student() {
        // Clean up dynamically allocated memory
        delete[] dynamicBuffer;
        std::cout << "Destructor Called for " << name << std::endl;
    }

    void displayInfo() {
        std::cout << "Student Information:" << std::endl;
        std::cout << "Name: " << name << std::endl;
        std::cout << "Age: " << age << std::endl;
        std::cout << "GPA: " << gpa << std::endl;
    }
};

int main() {
    // Demonstrating object creation and destruction
    {
        std::cout << "Creating first student:" << std::endl;
        Student student1("Alice Johnson");
        student1.displayInfo();

        std::cout << "\nCreating second student:" << std::endl;
        Student student2("Bob Smith");
        student2.displayInfo();
    }  // Objects go out of scope here, destructors are called

    std::cout << "\nExiting main function" << std::endl;
    return 0;
}

Compile and run the program:

g++ student.cpp -o student
./student

Example output:

Creating first student:
Parameterized Constructor Called
Student Information:
Name: Alice Johnson
Age: 0
GPA: 0

Creating second student:
Parameterized Constructor Called
Student Information:
Name: Bob Smith
Age: 0
GPA: 0

Destructor Called for Bob Smith
Destructor Called for Alice Johnson

Exiting main function

Key points about destructors:

  • Defined with ~ followed by the class name
  • Called automatically when an object is destroyed
  • Used to free dynamically allocated resources
  • Helps prevent memory leaks
  • No return type and no parameters

Important destructor characteristics:

  • Called when object goes out of scope
  • Automatically invoked by the compiler
  • Crucial for cleaning up dynamic memory
  • Helps manage system resources efficiently

Use Access Specifiers (public, private, protected)

In this step, you'll learn about access specifiers in C++ and how they control the visibility and accessibility of class members. We'll explore the differences between public, private, and protected access levels.

Open the student.cpp file in the WebIDE and modify the code to demonstrate access specifiers:

#include <iostream>
#include <string>

class Student {
private:
    // Private members: accessible only within the class
    std::string name;
    int age;
    double gpa;

protected:
    // Protected members: accessible within the class and its derived classes
    std::string school;

public:
    // Public members: accessible from anywhere
    Student(std::string studentName, int studentAge, double studentGPA) {
        name = studentName;
        age = studentAge;
        gpa = studentGPA;
        school = "Default School";
    }

    // Public method to demonstrate access to private members
    void displayInfo() {
        std::cout << "Student Information:" << std::endl;
        std::cout << "Name: " << name << std::endl;  // Accessing private member
        std::cout << "Age: " << age << std::endl;
        std::cout << "GPA: " << gpa << std::endl;
        std::cout << "School: " << school << std::endl;
    }

    // Public method to modify private members
    void updateGPA(double newGPA) {
        if (newGPA >= 0.0 && newGPA <= 4.0) {
            gpa = newGPA;
        }
    }
};

class GraduateStudent : public Student {
public:
    GraduateStudent(std::string name, int age, double gpa)
        : Student(name, age, gpa) {
        // Can access protected 'school' member from base class
        school = "Graduate School";
    }

    void displaySchool() {
        std::cout << "School: " << school << std::endl;
    }
};

int main() {
    Student student("Alice Johnson", 20, 3.75);
    student.displayInfo();  // Public method accessing private members

    // Uncommenting the lines below would cause compilation errors
    // student.name = "John";  // Error: Cannot access private member
    // student.age = 25;       // Error: Cannot access private member

    student.updateGPA(3.90);  // Modifying private member through public method
    student.displayInfo();

    GraduateStudent gradStudent("Bob Smith", 25, 3.90);
    gradStudent.displayInfo();
    gradStudent.displaySchool();

    return 0;
}

Compile and run the program:

g++ student.cpp -o student
./student

Example output:

Student Information:
Name: Alice Johnson
Age: 20
GPA: 3.75
School: Default School
Student Information:
Name: Alice Johnson
Age: 20
GPA: 3.90
School: Default School
Student Information:
Name: Bob Smith
Age: 25
GPA: 3.90
School: Graduate School
School: Graduate School

Key points about access specifiers:

  • private: Members are only accessible within the same class
  • protected: Members are accessible within the class and its derived classes
  • public: Members are accessible from anywhere
  • Help control data access and maintain encapsulation

Implement Inheritance Between Classes

In this step, you'll learn about inheritance in C++, a fundamental concept of object-oriented programming that allows creating new classes based on existing classes.

Open the student.cpp file in the WebIDE and modify the code to demonstrate inheritance:

#include <iostream>
#include <string>

// Base class
class Person {
protected:
    std::string name;
    int age;

public:
    // Constructor
    Person(std::string personName, int personAge) {
        name = personName;
        age = personAge;
    }

    // Method to display basic information
    void displayInfo() {
        std::cout << "Name: " << name << std::endl;
        std::cout << "Age: " << age << std::endl;
    }
};

// Derived class: Student inherits from Person
class Student : public Person {
private:
    double gpa;
    std::string major;

public:
    // Constructor that calls base class constructor
    Student(std::string studentName, int studentAge, double studentGPA, std::string studentMajor)
        : Person(studentName, studentAge) {
        gpa = studentGPA;
        major = studentMajor;
    }

    // Additional method specific to Student
    void displayStudentInfo() {
        // Calling base class method
        displayInfo();
        std::cout << "GPA: " << gpa << std::endl;
        std::cout << "Major: " << major << std::endl;
    }
};

// Another derived class: Employee inherits from Person
class Employee : public Person {
private:
    std::string company;
    double salary;

public:
    // Constructor that calls base class constructor
    Employee(std::string employeeName, int employeeAge, std::string employeeCompany, double employeeSalary)
        : Person(employeeName, employeeAge) {
        company = employeeCompany;
        salary = employeeSalary;
    }

    // Additional method specific to Employee
    void displayEmployeeInfo() {
        // Calling base class method
        displayInfo();
        std::cout << "Company: " << company << std::endl;
        std::cout << "Salary: $" << salary << std::endl;
    }
};

int main() {
    // Creating objects of derived classes
    Student student("Alice Johnson", 20, 3.75, "Computer Science");
    std::cout << "Student Information:" << std::endl;
    student.displayStudentInfo();

    std::cout << "\n";

    Employee employee("Bob Smith", 35, "Tech Corp", 75000.0);
    std::cout << "Employee Information:" << std::endl;
    employee.displayEmployeeInfo();

    return 0;
}

Compile and run the program:

g++ student.cpp -o student
./student

Example output:

Student Information:
Name: Alice Johnson
Age: 20
GPA: 3.75
Major: Computer Science

Employee Information:
Name: Bob Smith
Age: 35
Company: Tech Corp
Salary: $75000

Key points about inheritance:

  • Base class (Person) contains common attributes
  • Derived classes (Student, Employee) inherit from base class
  • Use : public BaseClassName to inherit
  • Can add new attributes and methods in derived classes
  • Can use base class methods in derived classes

Override Base Class Methods

In this step, you'll learn how to override base class methods in C++, allowing derived classes to provide their own implementation of methods inherited from the base class.

Open the student.cpp file in the WebIDE and modify the code to demonstrate method overriding:

#include <iostream>
#include <string>

class Animal {
protected:
    std::string name;

public:
    Animal(std::string animalName) : name(animalName) {}

    // Virtual keyword allows method to be overridden
    virtual void makeSound() {
        std::cout << "Some generic animal sound" << std::endl;
    }

    // Virtual method for displaying information
    virtual void displayInfo() {
        std::cout << "Animal Name: " << name << std::endl;
    }
};

class Dog : public Animal {
private:
    std::string breed;

public:
    Dog(std::string dogName, std::string dogBreed)
        : Animal(dogName), breed(dogBreed) {}

    // Override makeSound method
    void makeSound() override {
        std::cout << "Woof! Woof!" << std::endl;
    }

    // Override displayInfo method
    void displayInfo() override {
        // Call base class method first
        Animal::displayInfo();
        std::cout << "Breed: " << breed << std::endl;
    }
};

class Cat : public Animal {
private:
    std::string color;

public:
    Cat(std::string catName, std::string catColor)
        : Animal(catName), color(catColor) {}

    // Override makeSound method
    void makeSound() override {
        std::cout << "Meow! Meow!" << std::endl;
    }

    // Override displayInfo method
    void displayInfo() override {
        // Call base class method first
        Animal::displayInfo();
        std::cout << "Color: " << color << std::endl;
    }
};

int main() {
    // Create animal objects
    Animal genericAnimal("Generic Animal");
    Dog myDog("Buddy", "Labrador");
    Cat myCat("Whiskers", "Orange");

    // Demonstrate polymorphic behavior
    std::cout << "Generic Animal:" << std::endl;
    genericAnimal.displayInfo();
    genericAnimal.makeSound();

    std::cout << "\nDog:" << std::endl;
    myDog.displayInfo();
    myDog.makeSound();

    std::cout << "\nCat:" << std::endl;
    myCat.displayInfo();
    myCat.makeSound();

    return 0;
}

Compile and run the program:

g++ student.cpp -o student
./student

Example output:

Generic Animal:
Animal Name: Generic Animal
Some generic animal sound

Dog:
Animal Name: Buddy
Breed: Labrador
Woof! Woof!

Cat:
Animal Name: Whiskers
Color: Orange
Meow! Meow!

Key points about method overriding:

  • Use virtual keyword in base class to enable overriding
  • Use override keyword in derived class to explicitly override
  • Can call base class method using BaseClass::method()
  • Allows different implementations for the same method
  • Enables polymorphic behavior

Create Friend Functions for Access Control

In this step, you'll learn about friend functions in C++, which allow external functions or other classes to access private and protected members of a class.

Open the student.cpp file in the WebIDE and modify the code to demonstrate friend functions:

#include <iostream>
#include <string>

class BankAccount {
private:
    std::string accountHolder;
    double balance;

    // Declare friend functions
    friend void displayAccountDetails(const BankAccount& account);
    friend class AccountManager;

public:
    // Constructor
    BankAccount(std::string name, double initialBalance) {
        accountHolder = name;
        balance = initialBalance;
    }

    // Method to deposit money
    void deposit(double amount) {
        if (amount > 0) {
            balance += amount;
        }
    }
};

// Friend function that can access private members
void displayAccountDetails(const BankAccount& account) {
    std::cout << "Account Holder: " << account.accountHolder << std::endl;
    std::cout << "Current Balance: $" << account.balance << std::endl;
}

// Friend class that can access private members
class AccountManager {
public:
    // Method that can access private members of BankAccount
    void transferFunds(BankAccount& from, BankAccount& to, double amount) {
        if (from.balance >= amount) {
            from.balance -= amount;
            to.balance += amount;
            std::cout << "Transfer successful!" << std::endl;
        } else {
            std::cout << "Insufficient funds!" << std::endl;
        }
    }
};

int main() {
    // Create bank accounts
    BankAccount account1("Alice Johnson", 1000.0);
    BankAccount account2("Bob Smith", 500.0);

    // Use friend function to display account details
    std::cout << "Account 1 Details:" << std::endl;
    displayAccountDetails(account1);

    std::cout << "\nAccount 2 Details:" << std::endl;
    displayAccountDetails(account2);

    // Use friend class to transfer funds
    AccountManager manager;
    std::cout << "\nTransferring $200 from Alice to Bob:" << std::endl;
    manager.transferFunds(account1, account2, 200.0);

    std::cout << "\nUpdated Account Details:" << std::endl;
    displayAccountDetails(account1);
    displayAccountDetails(account2);

    return 0;
}

Compile and run the program:

g++ student.cpp -o student
./student

Example output:

Account 1 Details:
Account Holder: Alice Johnson
Current Balance: $1000

Account 2 Details:
Account Holder: Bob Smith
Current Balance: $500

Transferring $200 from Alice to Bob:
Transfer successful!

Updated Account Details:
Account Holder: Alice Johnson
Current Balance: $800
Account Holder: Bob Smith
Current Balance: $700

Key points about friend functions:

  • Declared using the friend keyword
  • Can access private and protected members of a class
  • Declared inside the class definition
  • Can be individual functions or entire classes
  • Breaks encapsulation, so use sparingly

Use Static Members and Methods

In this step, you'll learn about static members and methods in C++, which are shared across all instances of a class and belong to the class itself rather than individual objects.

Open the student.cpp file in the WebIDE and modify the code to demonstrate static members and methods:

#include <iostream>
#include <string>

class University {
private:
    std::string name;
    static int totalStudents;  // Static member variable
    static double totalTuition;  // Another static member variable

public:
    // Constructor
    University(std::string universityName) : name(universityName) {}

    // Method to add students
    void addStudents(int count) {
        totalStudents += count;
    }

    // Method to add tuition
    void addTuition(double amount) {
        totalTuition += amount;
    }

    // Static method to display total students
    static void displayTotalStudents() {
        std::cout << "Total Students Across All Universities: "
                  << totalStudents << std::endl;
    }

    // Static method to display total tuition
    static void displayTotalTuition() {
        std::cout << "Total Tuition Collected: $"
                  << totalTuition << std::endl;
    }

    // Static method to calculate average tuition
    static double calculateAverageTuition() {
        return (totalStudents > 0) ?
               (totalTuition / totalStudents) : 0.0;
    }
};

// Initialize static member variables outside the class
int University::totalStudents = 0;
double University::totalTuition = 0.0;

int main() {
    // Create university objects
    University harvard("Harvard University");
    University mit("MIT");
    University stanford("Stanford University");

    // Add students and tuition
    harvard.addStudents(5000);
    harvard.addTuition(75000000.0);

    mit.addStudents(4500);
    mit.addTuition(65000000.0);

    stanford.addStudents(4200);
    stanford.addTuition(60000000.0);

    // Call static methods directly on the class
    std::cout << "University Statistics:" << std::endl;
    University::displayTotalStudents();
    University::displayTotalTuition();

    // Calculate and display average tuition
    std::cout << "Average Tuition per Student: $"
              << University::calculateAverageTuition() << std::endl;

    return 0;
}

Compile and run the program:

g++ student.cpp -o student
./student

Example output:

University Statistics:
Total Students Across All Universities: 13700
Total Tuition Collected: $2e+08
Average Tuition per Student: $14598.5

Key points about static members and methods:

  • Shared across all instances of a class
  • Declared using static keyword
  • Can be accessed without creating an object
  • Belong to the class, not to individual objects
  • Useful for tracking class-wide information

Summary

In this lab, you learned how to define a class with private data members, which is an essential concept in object-oriented programming. Private data members help encapsulate and protect the internal state of an object. You also learned about the importance of public member functions, which allow controlled access to private data members. This helps maintain data integrity and control. Additionally, you explored the use of constructors, destructors, access specifiers, inheritance, method overriding, friend functions, and static members and methods, all of which are fundamental principles of object-oriented programming in C++.

Other C++ Tutorials you may like