Week 8: Introduction to Object-Oriented Programming
Explore the fundamental concepts of OOP using classes and objects in C++.
Explore Chapter 8Chapter 8: Basics of Object-Oriented Programming (OOP)
Core OOP Concepts.
Object-Oriented Programming (OOP) is a programming paradigm based on the concept of "objects", which can contain data in the form of fields (often known as attributes or properties) and code in the form of procedures (often known as methods). OOP aims to improve code organization, reusability, and maintainability, especially for complex software.
Key concepts in OOP include:
- Encapsulation: Bundling data (attributes) and methods (functions that operate on the data) within a single unit (an object). It often involves restricting direct access to some of an object's components (data hiding).
- Abstraction: Hiding complex implementation details and exposing only the essential features of an object. Users interact with the object through a simplified interface.
- Inheritance: A mechanism where a new class (derived or child class) inherits properties and methods from an existing class (base or parent class). This promotes code reuse and creates class hierarchies.
- Polymorphism: Literally "many forms." Allows objects of different classes to respond to the same message (method call) in different ways. Often achieved through virtual functions (discussed later).
This week, we'll focus on the foundational elements: classes and objects, attributes, methods, and access control.
Classes and Objects.
Classes: The Blueprint
A class is a user-defined blueprint or template from which objects are created. It defines a type, bundling together data members (attributes) and member functions (methods) that operate on that data.
You define a class using the `class` keyword.
class Dog {
public: // Access specifier (more on this later)
// Member Variables (Attributes)
std::string name;
std::string breed;
int age;
// Member Function (Method)
void bark() {
std::cout << name << " says Woof!" << std::endl;
}
}; // Note the semicolon after the class definition
Objects: Instances of a Class
An object is a concrete instance created from a class blueprint. When you create an object, memory is allocated for its member variables.
You create objects (instantiate a class) much like you declare variables of built-in types.
int main() {
Dog myDog; // Create an object (instance) of the Dog class named myDog
Dog anotherDog; // Create another Dog object
// Accessing member variables using the dot (.) operator
myDog.name = "Buddy";
myDog.breed = "Golden Retriever";
myDog.age = 3;
anotherDog.name = "Lucy";
// Calling member functions using the dot (.) operator
myDog.bark(); // Output: Buddy says Woof!
anotherDog.bark(); // Output: Lucy says Woof!
return 0;
}
Each object (`myDog`, `anotherDog`) has its own separate set of member variables (`name`, `breed`, `age`).
Access Specifiers (`public`, `private`, `protected`).
Access specifiers control the visibility and accessibility of class members (variables and methods) from outside the class. This is a key part of encapsulation.
- `public`: Members declared as `public` are accessible from anywhere - outside the class, in derived classes, and within the class itself.
- `private`: Members declared as `private` are accessible only from within the class itself (i.e., by its own member functions or friend functions/classes). This is the default access level if no specifier is provided for a class.
- `protected`: Similar to `private`, but `protected` members are also accessible from within derived classes (inheritance).
Good practice often involves making member variables `private` and providing `public` member functions (getters and setters) to access or modify them in a controlled way.
class Rectangle {
private: // Data members are typically private
double width;
double height;
public: // Member functions are often public
// Setter methods
void setWidth(double w) {
if (w > 0) width = w; // Add validation
}
void setHeight(double h) {
if (h > 0) height = h;
}
// Getter methods
double getWidth() { return width; }
double getHeight() { return height; }
// Method to calculate area
double getArea() {
return width * height;
}
};
int main() {
Rectangle rect;
// rect.width = 10; // Error! width is private
rect.setWidth(10.0); // OK, using public setter
rect.setHeight(5.0); // OK
std::cout << "Area: " << rect.getArea() << std::endl; // Output: 50
return 0;
}
Member Variables (Attributes) and Member Functions (Methods).
Member Variables (Attributes)
These are the data components of a class. They define the properties or state of objects created from the class. As seen above, they are declared within the class definition like regular variables, usually within a `private` section for good encapsulation.
class Circle {
private:
double radius; // Member variable
// ... maybe color, position, etc.
public:
// ... methods ...
};
Member Functions (Methods)
These are functions defined within the class scope. They operate on the data (member variables) of the specific object they are called on. They define the behavior or actions an object can perform.
Methods have access to all members (`public`, `private`, `protected`) of their own class.
class Counter {
private:
int count = 0; // Member variable, initialized
public:
void increment() { // Member function
count++; // Accesses the private member 'count'
}
void reset() { // Another member function
count = 0;
}
int getValue() { // Member function to access private data
return count;
}
};
int main() {
Counter myCounter;
myCounter.increment();
myCounter.increment();
std::cout << "Counter value: " << myCounter.getValue() << std::endl; // Output: 2
myCounter.reset();
std::cout << "Counter value: " << myCounter.getValue() << std::endl; // Output: 0
return 0;
}
We'll explore special member functions like constructors and destructors next week.