Object-Oriented Programming
Table of Contents
- Principles of OOP
- Class Implementation
- Pointer to Objects
- Constructors
this
Pointer- Array of Objects
- Dynamic Allocation and De-allocation of Memory
- Destructor
- Default Argument
- Member Functions with Reference Return Type
- Member Functions with
const
Return Type - Inline Member Functions
Principles of OOP
-
Encapsulation
- Wrapping data and methods into a single unit (class).
- Implementation details hidden from the outside world.
-
Inheritance
- One class (derived class) acquires the properties and behaviors of another class (base class).
- Promotes code reuse and hierarchical relationships.
-
Polymorphism
- Ability to take many forms.
- Typically achieved via function overloading, operator overloading, and virtual functions.
-
Abstraction
- Exposing only essential features and hiding internal details.
- Simplifies complexity by providing high-level interfaces.
Class Implementation
- Class Declaration: Defined using class keyword.
- Access Specifiers:
public
: Accessible from anywhere.private
: Accessible only within the class.protected
: Accessible within the class and derived classes.
Code Example:
File: point.h
#ifndef POINT
#define POINT
#define SIZE 3
class Point {
private:
double x;
double y;
char label[SIZE];
public:
Point();
Point(double a, double b);
void setX(double value);
void setY(double value);
void setLabel(const char* s);
double getX() const;
double getY() const;
void display();
};
#endif
File: point.cpp
#include <iostream>
#include <cstring>
#include "point.h"
Point::Point() : x(0), y(0) {}
Point::Point(double a, double b) : x(a), y(b) {}
void Point::setX(double value) {
x = value;
}
void Point::setY(double value) {
y = value;
}
void Point::setLabel(const char* s) {
std::strcpy(label, s);
}
double Point::getX() const {
return x;
}
double Point::getY() const {
return y;
}
void Point::display() {
std::cout << "Point label is: " << label;
std::cout << "x coordinate is: " << x;
std::cout << "y coordinate is: " << y << std::endl;
}
Pointer to Objects
- Syntax:
ClassName *ptr = &object
; - Usage:
- Access members using the arrow operator (
->
). - Dynamic allocation with
new
.
- Access members using the arrow operator (
Code Example:
File: point.h
#ifndef POINT
#define POINT
#define SIZE 3
class Point {
private:
double x;
double y;
char label[SIZE];
public:
Point();
Point(double a, double b);
void setX(double value);
void setY(double value);
void set_label(const char* s);
double getX() const;
double getY() const;
void display();
};
#endif
File: point.cpp
#include <iostream>
#include "point.h"
Point::Point() : x(0), y(0) {}
Point::Point(double a, double b) : x(a), y(b) {}
void Point::setX(double value) {
x = value;
}
void Point::setY(double value) {
y = value;
}
void Point::setLabel(const char* s) {
std::strcpy(label, s);
}
double Point::getX() const {
return x;
}
double Point::getY() const {
return y;
}
void Point::display() {
std::cout << "Point label is: " << label;
std::cout << "x coordinate is: " << x;
std::cout << "y coordinate is: " << y << std::endl;
}
void print(const Point* p, const Point& r) {
std::cout << p->getX();
std::cout << p->getY();
std::cout << r.getX();
std::cout << r.getY();
}
int main() {
Point a;
a.setX(120);
a.setY(200);
print(&a, a);
}
Constructor
- Purpose: Initialize objects upon creation.
- Types of Constructors:
- Default Constructor: No parameters.
- Parameterized Constructor: One or more parameters.
- Copy Constructor: Initializes an object using another object of the same class.
Code Example:
File: point.h
#ifndef POINT
#define POINT
class Point {
private:
double x;
double y;
public:
Point();
Point(double a, double b);
};
#endif
File: point.cpp
#include "point.h"
Point::Point() : x(0), y(0) {}
// This is also possible. However the other method is preferred.
// Point::Point() {
// x = 0;
// y = 0;
// }
Point::Point(double a, double b) : x(a), y(b) {}
// This is also possible. However the other method is preferred.
// Point::Point(double a, double b) {
// x = a;
// y = b;
// }
int main() {
Point a;
Point b(6, 7);
}
this
Pointer
- Definition: An implicit pointer to the current object.
- Usage: Commonly used when member variable names are shadowed by parameters, or to return the current object.
Code Example:
File: counter.h
#ifndef COUNTER
#define COUNTER
class Counter {
private:
int value;
public:
Counter();
void increment(int n);
};
#endif
File: counter.cpp
#include "counter.h"
Counter::Counter() : value(0) {}
void Counter::increment(int n) {
this->value += n;
}
int main() {
Counter x;
Counter y;
x.increment(5);
y.increment(6);
}
Array of Objects
- You can create arrays of class objects on the stack or heap.
- Access each element like a normal array element.
Code Example:
File: car.h
#ifndef CAR
#define CAR
#define SIZE 20
class Car {
private:
char make[SIZE];
int year;
double price;
public:
Car();
Car(const char* m, int y, double p);
const char* getMake() const;
void setMake(const char* m);
int getYear() const;
void setYear(int y);
double getPrice() const;
void setPrice(double p);
};
#endif
File: car.cpp
#include <cstring>
#include <iostream>
#include "car.h"
Car::Car() : year(0), price(0) {
for (int j = 0; j < SIZE; j++) {
this->make[j] = "\0";
}
}
Car::Car(const char* m, int y, double p) : year(y), price(p) {
assert(strlen(m) < SIZE);
strcpy(this->make, m);
}
const char* Car::getMake() const {
return this->make;
}
void Car::setMake(const char* m) {
assert(strlen(m) < SIZE);
strcpy(this->make, m);
}
int Car::getYear() const {
return this->year;
}
void Car::setYear(int y) {
this->year = y;
}
double Car::getPrice() const {
return this->price;
}
void Car::setPrice(double p) {
this->price = p;
}
void displayAll(Car x[], int n) {
for (int j = 0; j < n; j++) {
std::cout << x[j].getMake();
}
}
void swap(Car *x, Car *y) {
Car temp;
temp = *x;
*x = *y;
*y = temp;
}
int main() {
Car x[3];
x[0].setMake("Honda");
x[1].setMake("Ford");
displayAll(x, 2);
swap(&x[0], &x[1])
}
Dynamic Allocation and De-allocation of Memory
new
: Allocates memory on the heap.delete
: Frees memory previously allocated with new.new[]
anddelete[]
for arrays.
Code Example:
File: car.h
#ifndef CAR
#define CAR
#define SIZE 20
class Car {
private:
char make[SIZE];
int year;
double price;
public:
Car();
Car(const char* m, int y, double p);
const char* getMake() const;
void setMake(const char* m);
int getYear() const;
void setYear(int y);
double getPrice() const;
void setPrice(double p);
};
#endif
File: car.cpp
#include <cstring>
#include "car.h"
Car::Car() : year(0), price(0) {
for (int j = 0; j < SIZE; j++) {
this->make[j] = "\0";
}
}
Car::Car(const char* m, int y, double p) : year(y), price(p) {
assert(strlen(m) < SIZE);
strcpy(this->make, m);
}
const char* Car::getMake() const {
return this->make;
}
void Car::setMake(const char* m) {
assert(strlen(m) < SIZE);
strcpy(this->make, m);
}
int Car::getYear() const {
return this->year;
}
void Car::setYear(int y) {
this->year = y;
}
double Car::getPrice() const {
return this->price;
}
void Car::setPrice(double p) {
this->price = p;
}
int main() {
int *array;
array = new int[2];
array[0] = 79;
array[1] = 99;
delete[] array;
Car *x;
Car *y;
x = new Car;
y = new Car[3];
delete x;
delete[] y;
}
Destructor
- Definition: A special member function called when an object goes out of scope or is deleted.
- Syntax:
~ClassName()
- Purpose: Clean up resources, close files, release memory.
Code Example:
File: person.h
#ifndef PERON
#define PERSON
class Person {
private:
int age;
char* name;
public:
Person(const char* n, int a);
~Person();
const char* getName() const;
void setName(const char* n);
int getAge() const;
void setAge(int a);
};
#endif
File: person.cpp
#include <string.h>
#include <iostream>
#include "person.h"
Person::Person(const char* n, int a) : age(a) {
this->name = new char[strlen(n) + 1];
assert(this->name != 0);
strcpy(this->name, m);
}
Person::~Person() {
delete[] this->name;
this->name = NULL;
}
const char* Person::getName() const {
return this->name;
}
void Person::setName(const char* n) {
assert(strlen(n) <= strlen(this->name));
strcpy(this->name, n);
}
int Person::getAge() const {
return this->age;
}
void Person::setAge(int a) {
this->age = y;
}
int main() {
Person x("Alice", 14);
std::cout << x.getName();
std::cout << x.getAge();
}
Default Argument
- Usage: Provide default values for parameters in function declarations.
- Placement: Typically declared in header or class definition.
Code Example:
File: person.h
#ifndef PERON
#define PERSON
class Person {
private:
int age;
char* name;
public:
Person(const char* n, int a);
~Person();
const char* getName() const;
void setName(const char* n);
int getAge() const;
void setAge(int a);
};
#endif
File person.cpp
#include <string.h>
#include <iostream>
#include "person.h"
Person::Person(const char* n = NULL, int a = 0) {
this->age = a;
this->name = new char[strlen(n) + 1];
assert(this->name != 0);
strcpy(this->name, m);
}
Person::~Person() {
delete[] this->name;
this->name = NULL;
}
const char* Person::getName() const {
return this->name;
}
void Person::setName(const char* n) {
assert(strlen(n) <= strlen(this->name));
strcpy(this->name, n);
}
int Person::getAge() const {
return this->age;
}
void Person::setAge(int a) {
this->age = a;
}
int main() {
Person x();
Person y("Alice");
std::cout << y.getName();
Person z("John", 18)
std::cout << z.getName();
std::cout << z.getAge();
}
Member Functions with Reference Return Type
- Reason: Allows direct manipulation of the class's private members without copying.
- Example: Return a reference to a private member, so it can be changed outside the function.
Code Example:
File: mystring.h
#ifndef MYSTRING
#define MYSTRING
class MyString {
private:
int length;
char* storageM;
public:
MyString(const char* s);
~MyString();
const char& at(int i) const;
char& at(int i);
const char* getStorageM() const;
void setStorageM(const char* s);
int getLength() const;
void setLength(int l);
};
#endif
File: mystring.cpp
#include <string.h>
#include <iostream>
#include "mystring.h"
MyString::MyString(const char* s) {
this->length = (int) strlen(s);
this->storageM = new char[strlen(s) + 1];
assert(this->storageM != 0);
strcpy(this->storageM, s);
}
MyString::~MyString() {
delete[] this->storageM;
this->storageM = NULL;
}
const char* MyString::getStorageM() const {
return this->storageM;
}
void MyString::setStorageM(const char* s) {
assert(strlen(s) <= strlen(this->storageM));
strcpy(this->storageM, n);
}
int MyString::getLength() const {
return this->length;
}
void MyString::setLength(int l) {
this->length = l;
}
const char& MyString::at(int i) const {
assert(i >= 0 && i < this->length);
return storageM[i];
}
char& MyString::at(int i) {
assert(i > 0 && i < this->length);
return storageM[i];
}
int main() {
MyString x("Hello World!");
std::cout << x.at(0);
std::cout << x.at(6);
}
Member Functions with const
Return Type
- Usage: Return a constant reference or constant value to prevent modification.
- Example: Returning a
const
reference to ensure the caller cannot alter the internal data.
Code Example:
File: student.h
#ifndef STUDENT
#define STUDENT
class Student {
private:
int idM;
char nameM[50];
public:
Student();
Student(const char* name, const int id);
char* getNameMPointer() const;
const char* getNameMConstPointer() const;
void setNameM(const char* n);
};
#endif
File: student.cpp
#include <string.h>
#include "student.h"
Student::Student() {
strcpy(this->nameM, "None");
this->idM = 0;
}
Student::Student(const char* name, const int id) {
strcpy(this->nameM, name);
this->idM = id;
}
char* Student::getNameMPointer() const {
return this->nameM;
}
const char* Student::getNameMConstPointer() const {
return this->nameM;
}
void Student::setNameM(const char* n) {
assert(strlen(n) <= (int) strlen(this->nameM));
strcpy(this->name, n);
}
int main() {
char name[] = "Jane";
Student s(name, 123456);
char* bad = s.getNameMPointer();
bad[0] = "P"; // s.nameM is now "Pane"
const char* good = s.getNameMConstPointer();
good[0] = "P"; // invalid
}
Inline Member Function
- Definition: Inlining can be done implicitly or explicitly. A function declared with
inline
keyword, suggesting the compiler to replace the function call with the function body (optimization hint). - Usage: Often used for small, frequently called functions.
Code Example:
File: counter.h
#ifndef COUNTER
#define COUNTER
class Counter {
private:
int value;
public:
Counter();
// implicit inline
void increment(int n) {
value += n;
}
// explicit inline
inline void decrement(int n) {
value -= n;
}
};
#endif
File: counter.cpp
#include "counter.h"
Counter::Counter() : value(0) {}
int main() {
Counter x;
x.increment(5);
x.decrement(6);
}