Classes & Objects
A class is a user-defined type that groups member variables (data) and member functions (behavior) into a single unit. Once a class is defined, you can create as many objects (instances) of it as you need, each with its own independent set of member variables.
Defining a class
A Rectangle class
class Rectangle {
public:
// Member variables (the object's data / state)
double width;
double height;
// Member function (the object's behavior)
double area() const {
return width * height;
}
};width and height are member variables; area() is a member function. Inside a member function, you can refer to other members directly by name — no need to pass the object in as a parameter, because the function already knows which object it is operating on.
Creating objects: stack vs. heap
Like any other type in C++, objects can live on the stack (local, automatic storage, destroyed when they go out of scope) or on the heap (dynamic storage, created with new and requiring an explicit delete, or better, managed by a smart pointer — see the Dynamic Memory and Smart Pointers pages).
Stack allocation vs. heap allocation
#include <iostream>
#include <memory>
int main() {
// Stack: created here, destroyed automatically at end of scope.
Rectangle box;
box.width = 3.0;
box.height = 4.0;
std::cout << "Stack rectangle area: " << box.area() << "\n";
// Heap: created with new, must be deleted manually (or use a smart pointer).
Rectangle* heapBox = new Rectangle{5.0, 2.0};
std::cout << "Heap rectangle area: " << heapBox->area() << "\n";
delete heapBox; // forgetting this leaks memory
// Preferred modern style: let a smart pointer own the heap object.
auto managedBox = std::make_unique<Rectangle>(Rectangle{6.0, 6.0});
std::cout << "Managed rectangle area: " << managedBox->area() << "\n";
}class vs. struct: the one real difference
C++ inherits struct from C but extends it to support everything a class supports — member functions, constructors, inheritance, all of it. In modern C++, struct and class are almost interchangeable keywords.
Same members, different default access
struct Point {
int x; // public by default
int y; // public by default
};
class Point2 {
int x; // private by default
int y; // private by default
};
int main() {
Point p;
p.x = 1; // OK — struct members are public by default
p.y = 2;
Point2 p2;
// p2.x = 1; // Error: 'x' is private within this context
}A complete worked example
Rectangle: a small but complete class
#include <iostream>
class Rectangle {
public:
double width;
double height;
double area() const {
return width * height;
}
double perimeter() const {
return 2 * (width + height);
}
};
int main() {
Rectangle r;
r.width = 10.0;
r.height = 4.5;
std::cout << "Area: " << r.area() << "\n";
std::cout << "Perimeter: " << r.perimeter() << "\n";
}What's next
Right now
r.widthandr.heightmust be set manually after creation — constructors (next page) let objects initialize themselves.Marking
width/heightprivateand controlling access through methods is the subject of Access Specifiers and Encapsulation.Every member function implicitly receives a pointer to the object it was called on — that is the this pointer, covered a few pages ahead.