Class Basics
Class Basics¶
1. What is a Class?¶
A class is a user-defined type that combines data and functions.
#include <iostream>
#include <string>
class Person {
public:
// Member variables (data)
std::string name;
int age;
// Member function (behavior)
void introduce() {
std::cout << "Hello, I am " << name << ". "
<< "I am " << age << " years old." << std::endl;
}
};
int main() {
// Create object
Person p1;
p1.name = "Alice";
p1.age = 25;
p1.introduce(); // Hello, I am Alice. I am 25 years old.
Person p2;
p2.name = "Bob";
p2.age = 30;
p2.introduce();
return 0;
}
2. Access Specifiers¶
| Specifier | Inside Class | Derived Class | Outside |
|---|---|---|---|
public |
O | O | O |
protected |
O | O | X |
private |
O | X | X |
#include <iostream>
class Example {
public:
int publicVar = 1;
protected:
int protectedVar = 2;
private:
int privateVar = 3;
public:
void showAll() {
// All accessible inside class
std::cout << publicVar << std::endl;
std::cout << protectedVar << std::endl;
std::cout << privateVar << std::endl;
}
};
int main() {
Example ex;
std::cout << ex.publicVar << std::endl; // OK
// std::cout << ex.protectedVar << std::endl; // Error!
// std::cout << ex.privateVar << std::endl; // Error!
ex.showAll(); // All accessible internally
return 0;
}
Encapsulation¶
#include <iostream>
#include <string>
class BankAccount {
private:
std::string owner;
double balance;
public:
// Getter
std::string getOwner() const {
return owner;
}
double getBalance() const {
return balance;
}
// Setter
void setOwner(const std::string& name) {
owner = name;
}
void deposit(double amount) {
if (amount > 0) {
balance += amount;
}
}
bool withdraw(double amount) {
if (amount > 0 && amount <= balance) {
balance -= amount;
return true;
}
return false;
}
};
int main() {
BankAccount account;
account.setOwner("Alice");
account.deposit(1000);
std::cout << account.getOwner() << ": $"
<< account.getBalance() << std::endl;
account.withdraw(300);
std::cout << "After withdrawal: $" << account.getBalance() << std::endl;
return 0;
}
3. Constructor¶
A special function automatically called when an object is created.
Default Constructor¶
#include <iostream>
#include <string>
class Person {
public:
std::string name;
int age;
// Default constructor
Person() {
name = "Unknown";
age = 0;
std::cout << "Default constructor called" << std::endl;
}
};
int main() {
Person p; // Default constructor called
std::cout << p.name << ", " << p.age << std::endl;
return 0;
}
Parameterized Constructor¶
#include <iostream>
#include <string>
class Person {
public:
std::string name;
int age;
// Default constructor
Person() : name("Unknown"), age(0) {}
// Parameterized constructor
Person(std::string n, int a) {
name = n;
age = a;
}
};
int main() {
Person p1; // Default constructor
Person p2("Alice", 25); // Parameterized constructor
Person p3 = {"Bob", 30}; // C++11 initialization
std::cout << p1.name << ", " << p1.age << std::endl;
std::cout << p2.name << ", " << p2.age << std::endl;
std::cout << p3.name << ", " << p3.age << std::endl;
return 0;
}
Member Initializer List¶
#include <iostream>
#include <string>
class Person {
private:
std::string name;
int age;
const int id; // const member
public:
// Member initializer list (recommended)
Person(std::string n, int a, int i)
: name(n), age(a), id(i) // Initializer list
{
// Body
std::cout << "Person created: " << name << std::endl;
}
void show() const {
std::cout << "ID: " << id << ", " << name << ", " << age << std::endl;
}
};
int main() {
Person p("Alice", 25, 1001);
p.show();
return 0;
}
When to Use Initializer List¶
- const member initialization
- Reference member initialization
- Calling parent class constructor
- Performance (avoid unnecessary default construction)
4. Destructor¶
Automatically called when an object is destroyed.
#include <iostream>
class Resource {
private:
int* data;
public:
Resource(int size) {
data = new int[size];
std::cout << "Resource allocated" << std::endl;
}
~Resource() { // Destructor
delete[] data;
std::cout << "Resource freed" << std::endl;
}
};
int main() {
{
Resource r(100);
// r destroyed at end of block
}
std::cout << "After block ends" << std::endl;
return 0;
}
Output:
Resource allocated
Resource freed
After block ends
5. this Pointer¶
A pointer to the current object.
#include <iostream>
#include <string>
class Person {
private:
std::string name;
int age;
public:
Person(std::string name, int age) {
// Use this to distinguish member from parameter
this->name = name;
this->age = age;
}
// Return for method chaining
Person& setName(std::string name) {
this->name = name;
return *this; // Return self
}
Person& setAge(int age) {
this->age = age;
return *this;
}
void show() const {
std::cout << name << ", " << age << std::endl;
}
};
int main() {
Person p("Alice", 25);
// Method chaining
p.setName("Bob").setAge(30);
p.show(); // Bob, 30
return 0;
}
6. const Member Functions¶
Functions that do not modify the object.
#include <iostream>
#include <string>
class Person {
private:
std::string name;
int age;
public:
Person(std::string n, int a) : name(n), age(a) {}
// const member function: Cannot modify object
std::string getName() const {
// name = "Other"; // Error!
return name;
}
int getAge() const {
return age;
}
// non-const member function: Can modify object
void setAge(int a) {
age = a;
}
};
void printPerson(const Person& p) {
// const object can only call const member functions
std::cout << p.getName() << ", " << p.getAge() << std::endl;
// p.setAge(30); // Error!
}
int main() {
Person p("Alice", 25);
printPerson(p);
return 0;
}
7. Classes and Header Files¶
person.h¶
#ifndef PERSON_H
#define PERSON_H
#include <string>
class Person {
private:
std::string name;
int age;
public:
Person(std::string n, int a);
std::string getName() const;
int getAge() const;
void setAge(int a);
void introduce() const;
};
#endif
person.cpp¶
#include "person.h"
#include <iostream>
Person::Person(std::string n, int a) : name(n), age(a) {}
std::string Person::getName() const {
return name;
}
int Person::getAge() const {
return age;
}
void Person::setAge(int a) {
age = a;
}
void Person::introduce() const {
std::cout << "Hello, I am " << name << "." << std::endl;
}
main.cpp¶
#include <iostream>
#include "person.h"
int main() {
Person p("Alice", 25);
p.introduce();
return 0;
}
Compilation¶
g++ -c person.cpp -o person.o
g++ -c main.cpp -o main.o
g++ person.o main.o -o program
8. Struct vs Class¶
In C++, the only difference between struct and class is the default access specifier.
struct MyStruct {
int x; // Default: public
};
class MyClass {
int x; // Default: private
};
Convention¶
// struct: Data-centric, few methods
struct Point {
int x;
int y;
};
// class: Includes behavior, encapsulation
class Rectangle {
private:
Point topLeft;
Point bottomRight;
public:
int getArea() const;
};
9. Default Constructor Rules¶
#include <iostream>
class A {
public:
int value;
// No constructor - compiler generates default constructor
};
class B {
public:
int value;
B(int v) : value(v) {}
// User-defined constructor - no default constructor
};
class C {
public:
int value;
C(int v) : value(v) {}
C() = default; // Explicitly generate default constructor
};
class D {
public:
D() = delete; // Delete default constructor
};
int main() {
A a; // OK
// B b; // Error! No default constructor
B b(10); // OK
C c; // OK (default explicitly created)
C c2(20); // OK
// D d; // Error! Deleted
return 0;
}
10. Inline Member Functions¶
class Calculator {
public:
// Defined inside class: Automatically inline
int add(int a, int b) {
return a + b;
}
// External definition with inline
int multiply(int a, int b);
};
// Specify inline outside class
inline int Calculator::multiply(int a, int b) {
return a * b;
}
11. Practice Examples¶
Rectangle Class¶
#include <iostream>
class Rectangle {
private:
double width;
double height;
public:
// Constructors
Rectangle() : width(0), height(0) {}
Rectangle(double w, double h) : width(w), height(h) {}
// Getter/Setter
double getWidth() const { return width; }
double getHeight() const { return height; }
void setWidth(double w) {
if (w >= 0) width = w;
}
void setHeight(double h) {
if (h >= 0) height = h;
}
// Functions
double getArea() const {
return width * height;
}
double getPerimeter() const {
return 2 * (width + height);
}
void display() const {
std::cout << "Rectangle(" << width << " x " << height << ")" << std::endl;
std::cout << " Area: " << getArea() << std::endl;
std::cout << " Perimeter: " << getPerimeter() << std::endl;
}
};
int main() {
Rectangle r1;
r1.setWidth(5);
r1.setHeight(3);
r1.display();
Rectangle r2(10, 4);
r2.display();
return 0;
}
Student Class¶
#include <iostream>
#include <string>
#include <vector>
class Student {
private:
std::string name;
int id;
std::vector<int> scores;
public:
Student(std::string n, int i) : name(n), id(i) {}
void addScore(int score) {
if (score >= 0 && score <= 100) {
scores.push_back(score);
}
}
double getAverage() const {
if (scores.empty()) return 0;
int sum = 0;
for (int s : scores) {
sum += s;
}
return static_cast<double>(sum) / scores.size();
}
void display() const {
std::cout << "ID: " << id << ", Name: " << name << std::endl;
std::cout << "Scores: ";
for (int s : scores) {
std::cout << s << " ";
}
std::cout << std::endl;
std::cout << "Average: " << getAverage() << std::endl;
}
};
int main() {
Student s("Alice", 20210001);
s.addScore(85);
s.addScore(90);
s.addScore(78);
s.display();
return 0;
}
12. Summary¶
| Concept | Description |
|---|---|
class |
User-defined type |
public |
Accessible from anywhere |
private |
Accessible only within class |
protected |
Accessible in class and derived classes |
| Constructor | Called when object is created |
| Destructor | Called when object is destroyed |
this |
Pointer to current object |
const method |
Cannot modify object |
Next Step¶
Let's learn about operator overloading and copy/move in 08_Classes_Advanced.md!