Data Structures Review of Classes Dr.Ahmed Awad Classes Provide a way to define new user-defined types, complete with associated functions and data. Fundamental to Object Oriented Programming. Class Structure: class <class-name> { public: public-members; private: private-members; }; If no access specified is given, the default is private. 2 Classes - Example }; class Counter{ public: Counter(); int getCount(); void increaseBy(int x); private: int count; Public: Accessible from outside the class. Private: Accesible only from within the class (or friends of the class). 3 Classes - Example #include<iostream> using namespace std; class Counter { public: Counter(); int getCount(); void increaseBy(int); private: int count; }; Counter::Counter() { // constructor to initialize count = 0; // the values of class member. } int Counter::getCount() { // getter function. return count; } void Counter::increaseBy(int x) //setter funtion { count += x; } 4 Classes – Object Example void main() { Counter ctr; cout << ctr.getCount() << endl; ctr.increaseBy(3); cout << ctr.getCount() << endl; ctr.increaseBy(5); cout << ctr.getCount() << endl; cout << ctr.count<< endl; //error } 5 Const Member Function Known as accessor function. A member function which only reads class data. Will not change the object content. Example: void printCount() const; void Counter::printCount() const { count = 50; //error cout << count << endl; } 6 Constructor A special member function whose task is to perform an initialization for the data members. Invoked when a new class object comes into existence. It is possible to define different constructors and rely on function overloading to determine which one is called. Default Constructor: A constructor that has no arugments. 7 Destructor A member function that is automatically called when a class object ceases to exist. If a class comes into existence dynamically using new operator, the destructor will be called when this object is destroyed using delete operator. Has the same name of the class preceeded with ~ Needed when classes allocate resources, such as memory. Needed to avoid memory leaks. 8 Example- Vector Class Stores a vector by dynamically allocating an array of integers. class Vect { public: Vect(int); ~Vect(); private: int size; int* data; }; Vect::Vect(int n) { size = n; data = new int[n]; } void main() { Vect a(100); Vect b = a; //shallow copy } Does not copy the contents of the array. Rather, it copies the pointer to the array initial element. Vect::~Vect() { delete[] data; } 9 Copy Constructor Declared to take a single argument, which is a constant reference to an object of the same class. Example: Copy constructor for class T T(const T& t) It copies the data members from one class to another. Vect::Vect(const Vect& a) { size = a.size; data = new int[size]; for (int i = 0; i < size; i++) data[i] = a.data[i]; } 10 Operator Overloading Vect& Vect::operator =(const Vect& a) { if (this != &a) { delete[] data; Useful for chaining calls. size = a.size; Example A=B=C data = new int[size]; for (int i = 0; i < size; i++) data[i] = a.data[i]; return *this; } } 11 Classes with Dynamic Data Members Every class that allocates its own objects using new operator should define: A destructor to free the allocated objects. A copy constructor that copies the content of the data members. Overloaded assignment operator (=) that: Deallocates old storage. Allocates new storage. Copies all member variables. 12 Class Friends Complex data structures involve interactions of different classes. Friendship allows sharing information between classes. Friend Function: A function that can access class private data. Friendship is not transitive. Reasons for using Friend Functions: Syntax requirements (such as defining overloaded input/output operators). Closely related classes. 13 Friend Function- Example Overload stream extraction operator (<<) 14 Back to Vector Class- Declaration class Vector { friend istream& operator >> (istream&, Vector&); friend ostream& operator << (ostream&, Vector&); public: Vector(int = 10); Vector(const Vector&); Vector& operator=(const Vector&); static int getVectCount(); ~Vector(); private: int size; int* data; static int count; }; int Vector::count = 0; int Vector::getVectCount() { return count; } 15 Back to Vector Class- Constructors Vector::Vector(int s) { size = (s > 0 ? s : 10); data = new int[size]; for (int i = 0; i < size; i++) data[i] = 0; count++; } Vector::Vector(const Vector& A): size(A.size) { data = new int[size]; for (int i = 0; i < size; i++) data[i] = A.data[i]; count++; } 16 Back to Vector Class- Other Functions Vector& Vector::operator =(const Vector& A) { if(this != &A) { delete[] data; size = A.size; data = new int[size]; for (int i = 0; i < size; i++) data[i] = A.data[i]; } return *this; } Vector::~Vector() { delete[] data; count--; } 17 Back to Vector Class- Friend Functions istream& operator >> (istream& in, Vector& A) { for (int i = 0; i < A.size; i++) in >> A.data[i]; return in; } ostream& operator << (ostream& out, Vector& A) { for (int i = 0; i < A.size; i++) out << A.data[i] << " "; return out; } 18 Back to Vector Class- Main Example void main() { Vector V(5); cin >> V; cout << V << endl; Vector V2(V); cout << V2 << endl; Vector V3 = V2; cout << V3 << endl; } 19