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.
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:
Private Data Members:
- Declared using the
private:access specifier - Cannot be directly accessed from outside the class
- Provide data protection and encapsulation
- Declared using the
Data Types:
std::string name: Stores student's nameint age: Stores student's agedouble gpa: Stores student's grade point average
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 classprotected: Members are accessible within the class and its derived classespublic: 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 BaseClassNameto 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
virtualkeyword in base class to enable overriding - Use
overridekeyword 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
friendkeyword - 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
statickeyword - 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++.



