0% found this document useful (0 votes)
5 views

W10-Class and Object in C++

The document provides an overview of classes and objects in C++ programming, detailing member access specifiers, constructors, destructors, and operator overloading. It explains the need for user-defined types and how to implement classes with member variables and functions, emphasizing the importance of encapsulation. Additionally, it discusses copy constructors and the differences between shallow and deep copies in memory management.

Uploaded by

songjiany
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
5 views

W10-Class and Object in C++

The document provides an overview of classes and objects in C++ programming, detailing member access specifiers, constructors, destructors, and operator overloading. It explains the need for user-defined types and how to implement classes with member variables and functions, emphasizing the importance of encapsulation. Additionally, it discusses copy constructors and the differences between shallow and deep copies in memory management.

Uploaded by

songjiany
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 43

SC1008 C and C++ Programming

Assistant Professor WANG Yong


[email protected]
CCDS, Nanyang Technological University
Week 10
Class and Object
Outline
• Introduction to Class and Object
• Member Access Specifiers
• Constructor and Destructors
• Dynamic memory allocation in a Class
• this Pointer in C++
• Operator Overloading
• Friend Function

3
The Need for New Types
• A C++ “Class" is simply a very-slightly modified Structure
• As with structures, we sometimes want new types:
• A calendar program might want to store information
about dates, but C++ does not have a Date type
• A student registration system needs to store info about
students, but C++ has no Student type
• A music synthesizer app might want to store information
about users' accounts, but C++ has no Instrument type

4
Introduction to Class
• A user-defined data type
• Represents the set of properties or methods that are
common to all objects of one type
• A blueprint for an object
Example: Car
• Cars have different names and brands, but all share some
common properties (4 wheels, Speed Limit, Mileage range,
etc)

Classes are fundamental to implementing Object-Oriented Programming

5
Introduction to Object
• An instance of a class
• Represents the real-life entities
• Has an identity, state, and behavior. Each object contains data
and code to manipulate the data.
Example: “My Car”
• Characteristics like color, manufactured year, price, drive, and
break.

6
Introduction to Class
Elements of a Class
• member variables: State inside each object
• Also called "instance variables" or "fields"
• Declared as private
• Each object created has a copy of each field.
• member functions: Behavior that executes inside each
object
• Also called "methods"
• Each object created has a copy of each method
• The method can interact with the data inside that object
• Constructors and destructors are special type of member functions

7
Introduction to Class
The implementation of a Class
• When building a class, we provide an interface to the user of the class
that details how the class works. The user often does not have access
to the code itself, but the interface usually suffices to use the class
properly
• The interface is generally put into a header file, e.g., ClassName.h
• The header file shows the class functions and variables (even though
some may be private)
• The source code for the class member functions is held in a .cpp file,
e.g., ClassName.cpp
• The .cpp file is written by the implementer of the class, and they
implement all of the class functions
• The user generally does not have or need access to this code (though you
can get it for open source code libraries) 8
Class Implementation
• One toy example
Best Practice: Separate the class definition and member function
implementations into two files: classname.h and classname.cpp
// in MyClass.h // in MyClass.cpp
#ifndef MYCLASS_H #include "MyClass.h"
#define MYCLASS_H #include <iostream>

class MyClass { MyClass::MyClass(){ data = 0; }


public: MyClass::MyClass(int a){
MyClass(); data = a;
MyClass(int a); }
~MyClass(){
std::cout<<“Bye!” <<data void MyClass::doSomething() {
<<std::endl; std::cout << ”Do something!”
} << std::endl;
void doSomething(); }

private:
int data;
};

#endif // MYCLASS_H

9
Class Implementation
• One toy example

// in MyClass.h
#ifndef MYCLASS_H
#define MYCLASS_H

class MyClass {
public:
MyClass(); Header Guards in C++:
MyClass(int a); • Preprocessor directives that help to avoid
~MyClass(){
std::cout<<“Bye!” <<data errors that arise when the same function
<<std::endl; or variable or class is included/defined
} more than once
void doSomething();
private: • Another choice:
int data; #pragma once
};

#endif // MYCLASS_H

10
Class Implementation
• One toy example

// in MyClass.h
#ifndef MYCLASS_H Member Access Specifier
#define MYCLASS_H
Default Constructor
Overloaded
class MyClass {
public: Parameterized Constructor Constructors
MyClass();
MyClass(int a);
~MyClass(){ Destructor
std::cout<<“Bye!” <<data
<<std::endl; Member Function
}
void doSomething();
Member Variable
private:
int data;
}; Make sure your class definition
ends with a semicolon.
#endif // MYCLASS_H

11
Member Access Specifiers
• Classes can limit the access to their member functions and data
• The three types of access a class can grant are:
o Public — Accessible wherever the program has access to an object of
the class
o private — Accessible only to member functions of the class, not
accessible outside the class
o Protected — Accessible to member functions of the class and its
derived classes (i.e., child classes), not accessible outside the class

12
Member Access Specifiers
• One toy example

// in MyClass.h
Member variables of a class are often
#ifndef MYCLASS_H defined as private. Why?
#define MYCLASS_H
- We want to encapsulate them. We can
class MyClass {
public:
provide controlled access to them by
MyClass(); defining other public/protected member
MyClass(int a); functions, e.g., user-defined functions like
~MyClass(){ getter() and setter().
std::cout<<“Bye!” <<data
<<std::endl;
}
void doSomething();
private:
int data;
};

#endif // MYCLASS_H

13
Constructor
• Special member function that initializes the data members of a class
object
• Its name is exactly the same as the class name
• A constructor CANNOT return a value and has NO return type (NOT
even void)
• There are 3 types of constructors:
- Default constructors
- Parametrized constructors
- Copy constructors

14
Default Constructor
• A constructor that can be invoked without any arguments, e.g. a
constructor with an empty parameter list, or a constructor with
default values for all of its arguments
• Never define more than one default constructor for a class.
• If you fail to write a constructor for a class, the compiler will
automatically define a default constructor that leaves all data
members un-initialized

• Whenever you defined one or more non-default constructors (with


parameters ) for a class, the compiler will not automatically
provide a default constructor. If you still need a default constructor
(without parameters ), you must explicitly define it

15
Parametrized Constructor
• Pass arguments to constructors. The initial values are passed as
arguments to the constructor function
• The arguments passed to a constructor are typically used to initialise
the object’s member variables

16
Class Implementation
• One toy example Including the header file of the class
Detailed implementation of constructors
and other member functions.
// in MyClass.cpp
The scope resolution operator (i.e., #include "MyClass.h"
#include <iostream>
two colons ::) is used to indicate which
class the function belongs to. MyClass::MyClass(){ data = 0; }
MyClass::MyClass(int a){
data = a;
}
// in main.cpp void MyClass::doSomething() {
#include "MyClass.h" std::cout << ”Do something!”
#include <iostream> << std::endl;
using namespace std; }
int main() {
MyClass toyClass1;
toyClass1.doSomething();
cout<<
toyClass1.data<<endl;
MyClass toyClass2(10);
}
17
Class Implementation
• One toy example Including the header file of the class
Detailed implementation of constructors
and other member functions.
// in MyClass.cpp
The scope resolution operator (i.e., #include "MyClass.h"
#include <iostream>
two colons ::) is used to indicate which
class the function belongs to. MyClass::MyClass(){ data = 0; }
MyClass::MyClass(int a){
The default constructor will data = a;
be executed, i.e., data = 0. }
// in main.cpp void MyClass::doSomething() {
#include "MyClass.h" std::cout << ”Do something!”
#include <iostream> << std::endl;
using namespace std; }
int main() {
MyClass toyClass1;
toyClass1.doSomething();
cout<<
toyClass1.data<<endl;
MyClass toyClass2(10);
}
18
Class Implementation
• One toy example Including the header file of the class
Detailed implementation of constructors
and other member functions.
// in MyClass.cpp
The scope resolution operator (i.e., #include "MyClass.h"
#include <iostream>
two colons ::) is used to indicate which
class the function belongs to. MyClass::MyClass(){ data = 0; }
MyClass::MyClass(int a){
The default constructor will data = a;
be executed, i.e., data = 0. }
// in main.cpp void MyClass::doSomething() {
#include "MyClass.h" std::cout << ”Do something!”
#include <iostream> << std::endl;
using namespace std; }
int main() { Error!
MyClass toyClass1; “data” is private and cannot
toyClass1.doSomething(); be accessed outside the class.
cout<<
toyClass1.data<<endl; The parameterized constructor will be
MyClass toyClass2(10);
executed, i.e., data = 10.
}
19
Class Implementation
• When the class and member functions are small, we can define member
functions inside the class to improve readability --- but NOT recommended
for large/complex member functions and classes
#include <iostream>

class MyClass {
public:
MyClass() { data = 0; }
MyClass(int a) { data = a; }
~MyClass() {
std::cout << "Bye! " << data << std::endl;
}

void doSomething() {
std::cout << "Do something!" << std::endl;
}

private:
int data;
};

20
Class Implementation
• Constructors can initialize their members in two different ways.

• Assignment way (assignment statement in constructor’s method body): a


constructor can use the arguments passed to it to initialize member
variables in the constructor definition:
MyClass(int a) { data = a; }

• Initializer list way: a constructor can have an initializer list within the
definition but prior to the constructor body:
MyClass(int a): data(a) { }

//If there are more variables:

MyClass(int a, double b): data1(a), data2(b) { }

https://www.ibm.com/docs/en/zos/2.4.0?topic=only-initialization-base-classes-members-c 21
Class Implementation
• Update the class definition with the constructors using an initializer list

#include <iostream>

class MyClass {
public:
MyClass(): data(0) {}
MyClass(int a): data(a) {}
~MyClass() {
std::cout << "Bye! " << data << std::endl;
}

void doSomething() {
std::cout << "Do something!" << std::endl;
}

private:
int data;
};

22
Copy Constructor
• A copy constructor is a special constructor in C++ that initializes a
new object as a copy of an existing object
• There are two types of copy constructor
- Default copy constructor
- User-defined copy constructor

• If a copy constructor for a class is NOT defined explicitly (i.e., the


user-defined copy constructor), then the compiler will automatically
provide a copy constructor (i.e., the default copy constructor )
• If a user-defined copy constructor exists, the compiler will NOT
automatically generate the default copy constructor

23
Default Copy Constructor
#include <iostream>

class MyClass {
public:
MyClass();
MyClass(int a);

//No user-defined copy constructor here

~MyClass(){
std::cout<<"Bye!"<<data <<std::endl;
}
void doSomething();
private:
int data; The compiler-generated default copy
};
constructor is called when initializing
MyClass::MyClass(){ data = 0; }
MyClass::MyClass(int a){
an object from another or assigning
data = a; one object to another.
}

void MyClass::doSomething() { toyClass2.data and toyClass3.data are


std::cout << "Do something!"
<< std::endl; also assigned as 10 like toyClass1.
}

int main() {
MyClass toyClass1(10);
MyClass toyClass2 = toyClass1;
MyClass toyClass3(toyClass1);
} 24
Default Copy Constructor
• What the default copy constructor actually does is as follows:

MyClass::MyClass(const MyClass& other){


data = other.data;
}

• You can still explicitly define the default copy constructor in C++, but
it is NOT necessary and NOT recommended.

25
User-defined Copy Constructor
#include <iostream>

class MyClass {
public: The user-defined copy
MyClass();
MyClass(int a); constructor MUST take a
// User-defined copy constructor const reference of the same
MyClass(const MyClass &obj) {
data = obj.data * 2; class as the parameter.
std::cout << "User-defined Copy constructor
is called!" << std::endl;
}
~MyClass(){
std::cout<<"Bye! "<<data <<std::endl; The user-defined copy
}
void doSomething(); constructor is called.
private:
int data;
}; toyClass2.data is 20 now!
MyClass::MyClass(){ data = 0; }
MyClass::MyClass(int a){
data = a;
}

void MyClass::doSomething() {
std::cout << "Do something!"
<< std::endl;
}

int main() {
MyClass toyClass1(10);
MyClass toyClass2 = toyClass1;
}
26
Shallow Copy vs. Deep Copy
• Shallow Copy:
- An object is created by simply copying the data of all variables of the
original object
- If a variable of the object are dynamically allocated memory (e.g.,
new), the copied object variable will also refer to the same memory
location -- only the memory address is copied!

• Deep Copy:
- It copies the data of all variables
- For variables using dynamically allocated memory, it also allocates
new memory resources to store the same value.

27
Shallow Copy vs. Deep Copy
• Default copy constructor can perform only shallow copy
#include <iostream>
class MyClass {
public:
int* data; // Pointer to dynamically allocated memory

// Constructor
MyClass(int val) {
data = new int(val); // Allocating memory
std::cout << "Constructor called, allocating memory at " << data <<
std::endl;
}

//No user-defined copy constructor here

// Destructor
~MyClass() {
std::cout << "Destructor called, freeing memory at " << data <<
std::endl;
delete data; // Deallocating memory
}
};

int main() {
MyClass obj1(10); // Constructor called
MyClass obj2 = obj1; // Default copy constructor called – Shallow Copy!!!

// Modifying obj2 will also affect obj1 due to shared memory


*obj2.data = 20;

std::cout << "obj1.data: " << *obj1.data << std::endl;


std::cout << "obj2.data: " << *obj2.data << std::endl;

return 0; // Destructor called twice, leading to double deletion (ERROR!)


}
28
Shallow Copy vs. Deep Copy
• Default copy constructor can perform only shallow copy

Output
Constructor called, allocating memory at 0x1fff2b0
obj1.data: 20
obj2.data: 20
Destructor called, freeing memory at 0x1fff2b0
Destructor called, freeing memory at 0x1fff2b0
free(): double free detected in tcache 2
Aborted

29
Destructor
• A special member function that is automatically called whenever an
object of its class ceases to exist. Its main purpose is to release any
resources that the corresponding constructor allocated
• A destructor’s name is the same as the name of the class it belongs
to, except that the name is preceded by a tilde symbol (~)
• The destructor does not have arguments, and has no return type not
even void
• A destructor should be declared in the public section of the class
• There cannot be more than one destructor in a class.
• When a destructor is NOT specified in a class, compiler generates a
default destructor
• Generally, destructors are called in the reverse order of constructor
calls
30
Destructor
• Destructor is often used to free dynamically allocated memory,
avoiding memory leakage!
#include <iostream>
using namespace std;

class MyClass {
public:
int* data;
int size;

MyClass(int val) {// Constructor


data = new int(val);
size = val;
cout << "Constructed! The array size is " << size << endl;
}

~MyClass() {// Destructor


cout << "Destroyed! The array size is " << size << endl;
delete data;
}
};

int main() {

MyClass obj1(10);
MyClass obj2(20);
MyClass obj3(30);

return 0;
} 31
Destructor
• Destructors are called in the reverse order of constructor calls

Output
Constructed! The array size is 10
Constructed! The array size is 20
Constructed! The array size is 30
Destroyed! The array size is 30
Destroyed! The array size is 20
Destroyed! The array size is 10

32
The this pointer in C++
• The this pointer in C++ is an implicit pointer that stores the
memory address of the calling object
• It is available in the member functions of a class and allows access
to its own members
- We will use arrow -> instead of dot . to access its members, as
this is a pointer
• It is often used to 1) avoid naming conflicts and 2) return *this
for method chaining

33
The this pointer in C++
#include <iostream>
using namespace std;

class MyClass {
private:
int number;

public:
// Constructor
MyClass(int number) {
this->number = number; // Using `this` to resolve naming conflict
}

MyClass& setValue(int x) {
this->number = x;
return *this;
} // this will allow method chaining like: obj.setValue(10).display();

// Display function using `this` pointer


void display() {
cout << "Object Number: " << this->number << endl;
cout << "`this` Pointer Address: " << this << endl;
}
}; Output
Object Number: 100
int main() { `this` Pointer Address: 0x7fff8c4abd6c
MyClass obj1(100), obj2(200); Object Number: 200
obj1.display(); `this` Pointer Address: 0x7fff8c4abd68
obj2.display(); Object Number: 10
obj2.setValue(10).display(); `this` Pointer Address: 0x7fff8c4abd68
return 0;
}
34
Operator Overloading
• Operator overloading in C++ allows us to define the behavior of operators
for user-defined types, i.e., classes or structures, improving code readability
and usability

• To overload an operator, we use a special function form called an operator


function, i.e., operatorop (argument-list). For example,
o operator+ (argument-list) // overload operator +
o operator<< (argument-list) // overload operator <<
• Suppose you define an operator+() member function to overload operator
+ for a class named Salesperson, and district2, sid and sara are
objects of Salesperson class, then
district2 = sid + sara;
district2 = sid.operator+(sara);
will be equivalent.
35
Operator Overloading
#include <iostream>
using namespace std; The overloaded operator+ is
class MyClass {
doing the same job as
private: member function sum()!
int value;

public:
MyClass(int v) {value = v; } // Constructor

// Overloading the + operator


MyClass operator+(const MyClass& obj) const {
You can also use the operator
return MyClass(value + obj.value); function:
} MyClass obj3 =
// Function sum() that does the same as operator+ obj1.operator+(obj2);
MyClass sum(const MyClass& obj) const {
return MyClass(value + obj.value);
}

void display() { cout<< ”Value: " <<value<<endl; }


};

int main() {
MyClass obj1(10), obj2(20); Output
MyClass obj3 = obj1 + obj2; // Using overloaded + operator Value: 30
obj3.display();
MyClass obj4 = obj1.sum(obj2); // Using sum() function
Value: 30
obj4.display();

return 0;
}
36
Operator Overloading
#include <iostream>
using namespace std;
const after the member
function specifies that it is a
class MyClass {
private:
“read-only” function that will not
int value; alter the object of the class.
public:
MyClass(int v) {value = v; } // Constructor

// Overloading the + operator


MyClass operator+(const MyClass& obj) const { Can we
return MyClass(value + obj.value); overload << to
}
print the object
// Function sum() that does the same as operator+ content?
MyClass sum(const MyClass& obj) const {
return MyClass(value + obj.value);
}

void display() { cout<< ”Value: " <<value<<endl; }


};

int main() {
MyClass obj1(10), obj2(20); Output
MyClass obj3 = obj1 + obj2; // Using overloaded + operator Value: 30
obj3.display();
MyClass obj4 = obj1.sum(obj2); // Using sum() function
Value: 30
obj4.display();

return 0;
}
37
Overloading <<
• Can we define the operator<<() function as a member function here?
- Not appropriate!

• The statement like


cout << obj3;
uses two objects, and is equivalent to
operator<<(cout,obj3); with the ostream class object (cout)
first.
• If we define overload the operator << as a member function, the class
object itself obj3 will be the first parameter, which yields:
obj3 << cout;
which is quite confusing!

38
Friend and Friend Functions
• In C++, private members of a class cannot be accessed directly outside the
class. A friend in C++ provides access to private and protected members
of another class. Friends come in three varieties:
- Friend functions
- Friend classes
- Friend member functions
• By making a function a friend to a class, you allow the function the same
access privileges that a member function of the class has.

39
Friend Functions
• Place a prototype in the class declaration and prefix the declaration with
the keyword friend:
friend ostream& operator<<(ostream& out, const MyClass& obj);

• Write the function definition without MyClass:: qualifier

friend ostream& operator<<(ostream& out, const MyClass& obj)


{
out << obj.value;
return out;
}

40
Operator Overloading with Friend
Function
#include <iostream>
using namespace std;

class MyClass {
private:
int value;
public:
MyClass(int v) {value = v; }

// Overloading the + operator


MyClass operator+(const MyClass& obj) const {
int sum = value + obj.value;
return MyClass(sum);
}

// Declaring friend function to overload << operator


friend ostream& operator<<(ostream& out, const MyClass& obj);
};

// Overloading the << operator for output


ostream& operator<<(ostream& out, const MyClass& obj) {
out << "value: " << obj.value;
return out;
}

int main() {
MyClass obj1(10), obj2(20);
MyClass obj3 = obj1 + obj2; // Using overloaded + operator
cout << obj3 << endl;

return 0;
}
41
References:

[1] Prata, Stephen. C++ primer plus.


Sams Publishing, 2002, 5th edition.
Chapters 10, 11, 12.

42
Questions?

Thank You!

You might also like