Classes & Objects
Introduction to Classes
Classes are user-defined data types that encapsulate data and functions. They are the foundation of object-oriented programming in C++.
Simple Class Example
#include <iostream>
#include <string>
using namespace std;
class Student {
private:
string name;
int age;
double gpa;
public:
// Constructor
Student(const string& n, int a, double g) {
name = n;
age = a;
gpa = g;
}
// Getter methods
string getName() const { return name; }
int getAge() const { return age; }
double getGPA() const { return gpa; }
// Method to display information
void displayInfo() const {
cout << "Name: " << name << ", Age: " << age << ", GPA: " << gpa << endl;
}
};
int main() {
Student student1("Alice", 20, 3.8);
student1.displayInfo();
return 0;
}Encapsulation
Bundling data and methods together, hiding internal details
Abstraction
Providing a simplified interface to complex functionality
Inheritance
Creating new classes based on existing ones
Polymorphism
Using one interface for different underlying forms
Basic Class Definition
Here's how to define a simple class:
Simple Class Example
#include <iostream>
#include <string>
using namespace std;
class Student {
private: // Private members (data hiding)
string name;
int age;
double gpa;
public: // Public members (interface)
// Constructor
Student(const string& n, int a, double g) {
name = n;
age = a;
gpa = g;
}
// Getter methods
string getName() const {
return name;
}
int getAge() const {
return age;
}
double getGPA() const {
return gpa;
}
// Setter methods
void setGPA(double newGPA) {
if (newGPA >= 0.0 && newGPA <= 4.0) {
gpa = newGPA;
}
}
// Method to display information
void displayInfo() const {
cout << "Name: " << name << endl;
cout << "Age: " << age << endl;
cout << "GPA: " << gpa << endl;
}
};
int main() {
// Create objects
Student student1("Alice", 20, 3.8);
Student student2("Bob", 19, 3.5);
// Use methods
student1.displayInfo();
cout << "---" << endl;
student2.displayInfo();
// Modify using setter
student1.setGPA(3.9);
cout << "Updated GPA: " << student1.getGPA() << endl;
return 0;
}Constructors and Destructors
Constructors initialize objects, while destructors clean up resources:
Constructors and Destructors
#include <iostream>
#include <string>
using namespace std;
class Rectangle {
private:
double width;
double height;
public:
// Default constructor
Rectangle() {
width = 0.0;
height = 0.0;
cout << "Default constructor called" << endl;
}
// Parameterized constructor
Rectangle(double w, double h) {
width = w;
height = h;
cout << "Parameterized constructor called" << endl;
}
// Copy constructor
Rectangle(const Rectangle& other) {
width = other.width;
height = other.height;
cout << "Copy constructor called" << endl;
}
// Destructor
~Rectangle() {
cout << "Destructor called for rectangle "
<< width << "x" << height << endl;
}
// Methods
double getArea() const {
return width * height;
}
double getPerimeter() const {
return 2 * (width + height);
}
void display() const {
cout << "Rectangle: " << width << " x " << height
<< " (Area: " << getArea() << ")" << endl;
}
};
int main() {
cout << "Creating rectangles:" << endl;
Rectangle rect1; // Default constructor
Rectangle rect2(5.0, 3.0); // Parameterized constructor
Rectangle rect3 = rect2; // Copy constructor
cout << "\nRectangle information:" << endl;
rect1.display();
rect2.display();
rect3.display();
cout << "\nExiting main (destructors will be called):" << endl;
return 0;
}Access Specifiers
C++ provides three access levels for class members:
| Access Level | Same Class | Derived Class | Outside Class |
|---|---|---|---|
private | β | β | β |
protected | β | β | β |
public | β | β | β |
Access Specifiers Example
#include <iostream>
using namespace std;
class BankAccount {
private:
double balance; // Only accessible within the class
string accountNumber; // Hidden from outside access
protected:
int accountType; // Accessible in derived classes
public:
string ownerName; // Accessible everywhere
// Constructor
BankAccount(const string& owner, const string& accNum, double initialBalance) {
ownerName = owner;
accountNumber = accNum;
balance = initialBalance;
accountType = 1; // Default type
}
// Public methods to access private data
double getBalance() const {
return balance;
}
void deposit(double amount) {
if (amount > 0) {
balance += amount;
cout << "Deposited $" << amount << endl;
}
}
bool withdraw(double amount) {
if (amount > 0 && amount <= balance) {
balance -= amount;
cout << "Withdrew $" << amount << endl;
return true;
}
cout << "Insufficient funds or invalid amount" << endl;
return false;
}
void displayInfo() const {
cout << "Owner: " << ownerName << endl;
cout << "Balance: $" << balance << endl;
// cout << "Account: " << accountNumber << endl; // Can access private here
}
};
int main() {
BankAccount account("John Doe", "123456789", 1000.0);
// Can access public members
cout << "Account holder: " << account.ownerName << endl;
// Can use public methods
account.deposit(500.0);
account.withdraw(200.0);
account.displayInfo();
// Cannot access private members directly
// cout << account.balance; // Error!
// cout << account.accountNumber; // Error!
return 0;
}Static Members
Static members belong to the class rather than individual objects:
Static Members Example
#include <iostream>
using namespace std;
class Counter {
private:
int value;
static int totalObjects; // Static data member
public:
// Constructor
Counter(int val = 0) : value(val) {
totalObjects++; // Increment when object is created
}
// Destructor
~Counter() {
totalObjects--; // Decrement when object is destroyed
}
// Regular member function
int getValue() const {
return value;
}
void setValue(int val) {
value = val;
}
// Static member function
static int getTotalObjects() {
return totalObjects; // Can only access static members
// return value; // Error! Cannot access non-static members
}
// Static member function to display count
static void displayCount() {
cout << "Total Counter objects: " << totalObjects << endl;
}
};
// Definition of static member (required outside class)
int Counter::totalObjects = 0;
int main() {
cout << "Initial count: ";
Counter::displayCount(); // Call static function using class name
Counter c1(10);
Counter c2(20);
cout << "After creating 2 objects: ";
Counter::displayCount();
{
Counter c3(30);
cout << "After creating 3rd object: ";
Counter::displayCount();
} // c3 goes out of scope and is destroyed
cout << "After c3 is destroyed: ";
Counter::displayCount();
// Can also call static function through object
cout << "Total objects (via object): " << c1.getTotalObjects() << endl;
return 0;
}Friend Functions
Friend functions can access private and protected members of a class:
Friend Functions Example
#include <iostream>
#include <cmath>
using namespace std;
class Point {
private:
double x, y;
public:
Point(double xVal = 0, double yVal = 0) : x(xVal), y(yVal) {}
void display() const {
cout << "(" << x << ", " << y << ")";
}
// Declare friend function
friend double distance(const Point& p1, const Point& p2);
friend Point midpoint(const Point& p1, const Point& p2);
// Friend class declaration (if needed)
friend class Line;
};
// Friend function definition
double distance(const Point& p1, const Point& p2) {
// Can access private members x and y directly
double dx = p1.x - p2.x;
double dy = p1.y - p2.y;
return sqrt(dx * dx + dy * dy);
}
Point midpoint(const Point& p1, const Point& p2) {
// Can access private members directly
return Point((p1.x + p2.x) / 2, (p1.y + p2.y) / 2);
}
// Example of friend class
class Line {
private:
Point start, end;
public:
Line(const Point& s, const Point& e) : start(s), end(e) {}
void displayLine() const {
cout << "Line from ";
start.display();
cout << " to ";
end.display();
cout << endl;
// Can access private members of Point because Line is a friend
cout << "Start coordinates: x=" << start.x << ", y=" << start.y << endl;
cout << "End coordinates: x=" << end.x << ", y=" << end.y << endl;
}
};
int main() {
Point p1(3, 4);
Point p2(7, 1);
cout << "Point 1: ";
p1.display();
cout << endl;
cout << "Point 2: ";
p2.display();
cout << endl;
cout << "Distance: " << distance(p1, p2) << endl;
Point mid = midpoint(p1, p2);
cout << "Midpoint: ";
mid.display();
cout << endl;
Line line(p1, p2);
line.displayLine();
return 0;
}Class Best Practices
Encapsulation
Keep data members private and provide public methods for access
Constructor Initialization
Use initialization lists for better performance and const members
Const Correctness
Mark methods const if they don't modify object state
RAII Principle
Resource Acquisition Is Initialization - manage resources in constructors/destructors
Single Responsibility
Each class should have one reason to change
Meaningful Names
Use descriptive names for classes, methods, and members