Professional Documents
Culture Documents
OOP w04 Publish
OOP w04 Publish
1
CONTENTS
Introduction
Constructor
Destructor
Assignment operator (‘=’)
Parameters problems
Type–casting
Other problems
2
INTRODUCTION
Class of C++ includes: property &
method
Property and method have the scopes
◦ public: the scope of access is outside and
inside the class
◦ private: the scope of access is inside the class
class phanso{ void main(){
private: phanso p; Valid because the scope of ‘nhap’ is public
int tu; p.nhap(2, 3);
int mau; p.tu = 4;
public: }
void nhap(int, int);
void xuat(); Invalid because the scope of ‘tu’ is private
};
3
CONSTRUCTOR
Initializing the object’s data can use
◦ Function (example: the function ‘nhap(int,
int)’): If developer forgets calling this function,
the object will contain ‘rubbish’ data
◦ Constructor method
The constructor’s feature:
◦ Its name is the same as class name & has no
return-type
◦ Automatically run when initializing the object
to prepare the data for the object.
◦ Has many overloading constructor methods
4
CONSTRUCTOR
Types of constructors
class PhanSo{
private: Default constructor
int tu, mau;
public: Constructor with enough parameters
PhanSo();
PhanSo(int, int); Constructor from another object
PhanSo(const PhanSo&)
};
PhanSo::PhanSo(){
tu = 0; mau = 1; void main(){
} PhanSo p(2, 3);
PhanSo::PhanSo(int t, int m){ PhanSo q(p);
tu = t; mau = m; PhanSo t();
} cout << p.tu << “/” << p.mau << endl;
PhanSo::PhanSo(const PhanSo& p){ cout << q.tu << “/” << q.mau << endl;
tu = p.tu; mau = p.mau; cout << t.tu << “/” << t.mau << endl;
} }
5
CONSTRUCTOR
Some notes:
◦ If we do not declare/define any constructor, the compiler
provides default constructor
class PhanSo{
int tu, mau;
public:
void xuat();
void nhap(int, int);
//…
};
void main(){ PhanSo t(); }
9
COMPARISON WITH C# & JAVA
C# and Java support “constructor
chaining” allowing this constructor to call
that constructor in the same class
Line Code C#
1 // Declare class
2 class PhanSo {
3 private int tu;
4 private int mau;
5 public PhanSo(): this(0, 1) {} // call other constructor
6 public PhanSo(int t, int m) {
7 tu = t;
8 mau = m;
9 }
10 };
10
COMPARISON WITH C# & JAVA
In C# and Java, if sub-class’ s constructor
calls base-class’s constructor, the
implementation of virtual function called
in base-class’s constructor is the
implementation of the nearest sub-class
In C++, if sub-class’ s constructor calls
base-class’s constructor, the
implementation of virtual function called
in base-class’s constructor is the
implementation of the base-class
11
COMPARISON WITH C# & JAVA
C++:
#include <iostream>
using namespace std;
class lopA {
public:
lopA();
virtual void logging(); //virtual method
};
class lopB: public lopA {
public:
2 lopB() {}
void logging(); // no need to add virtual keyword
};
3 lopA::lopA() {logging();}
4 void lopA::logging() {cout << “Phuong thuc logging cua lop A” << endl;}
void lopB::logging() {cout << “Phuong thuc logging cua lop B” << endl;}
void main(){
1 lopB b;
}
12
COMPARISON WITH C# & JAVA
C#
class lopA {
3 public lopA() {logging();}
public virtual void logging() { Console.WriteLine(“Phuong thuc logging cua lop A\n”); }
};
class lopB: lopA {
2 public lopB() {}
4 public override void logging() { Console.WriteLine(“Phuong thuc logging cua lop B\n”); }
};
class Program {
1 static void Main(string[] args) { lopB b = new lopB(); }
}
Java
class lopA {
3 public lopA() {logging();}
public void logging() { System.out.println(“Phuong thuc logging cua lop A\n”); }
};
class lopB extends lopA {
2 public lopB() {}
4 public void logging() { System.out.println(“Phuong thuc logging cua lop B\n”); }
};
public class TestConstructor {
1 public static void main() { lopB b = new lopB(); }
}
13
COMPARISON WITH C# & JAVA
Some notes:
◦ In C# and Java, if the constructor is error, the
destructor automatically is called, but not in C++
◦ C# & Java don’t support default copy constructor
◦ C# supports static constructor, but not in Java &
C++
◦ C#’s static constructor: static className()
This method has no access modifier and parameter
This method is called before the first instance’s
initialization and the static members’ definition
This method is automatically called
14
DESTRUCTOR
Automatically called when the object is
useless and destroyed
Revoke the resource allocated for the objects
in their life
Cleaning up helps to resist the memory leak:
◦ The program is terminated due to lacking the
memory
◦ The other softwares cannot run due to the fact
that our program uses all the memory
◦ After our program runs, the computer hangs up
15
DESTRUCTOR (THE FEATURES)
Its name is the same as the class name
with ‘~’
Has no parameter & returned value
Each class has ONLY ONE destructor
Automatically run when the object is out
of usage scope
Run only ONE time
16
DESTRUCTOR
Example: consider MyIntArray
class MyIntArray{ void main(){
private: MyIntArray a(10);
int *pArr; int size; MyIntArray* b = new MyIntArray(20);
public: //…
MyIntArray(int); delete b;
~MyIntArray(); }
//…
}; 1. The destructor of object ‘a’ will be
MyIntArray::~MyIntArray(){ automatically called
if(size > 0){ 2. The destructor of ‘b’ will be automatically
size = 0; delete []pArr; pArr = NULL; called when running the statement ‘delete b’
}
}
MyIntArray::MyIntArray(int n){
size = n;
pArr = new int[size];
for(int i = 0; i < size; i++)
pArr[i] = 0;
} 17
COMPARISON WITH C# & JAVA
C# and Java do not allow programmer to
implement destructor method
C# and Java have garbage collector
mechanism
Garbage collector mechanism
automatically deallocates unused memory
Some mistakes of C++’s programmer
◦ Forget to free the allocated memory
◦ Still use the deallocated memory
◦ Free the memory being used
18
ASSIGNMENT OPERATOR
Operator helps the statement be more
natural
◦ Example:
PhanSo a(1, 2), b(2, 3);
PhanSo kq = a + b;
Theoperator may be binary or unary
Some operators cannot be overloaded
◦ Operators ‘.’, ‘?:’, ‘sizeof’ (in C)
◦ Operators ‘::’, ‘.*’, ‘typeid’ (in C++)
19
ASSIGNMENT OPERATOR
Assignment operator is used to assign the
value of this object to that object
C++ provides the default assignment
operator, copying each field from this
object to that object
Class with pointer field needs to re-define
the assignment operator
Class without pointer field doesn’t need
to re-define the assignment operator
20
ASSIGNMENT OPERATOR
Example: operator ‘=’ in MyIntArray
class MyIntArray{ void main(){
private: MyIntArray a, b, c(3);
int *pArr; int size; a = b = c;
public: }
MyIntArray& operator=(const MyIntArray&);
//… a b c
};
MyIntArray& MyIntArray::operator=(const MyIntArray& src){
=
if(this != &src){
delete []pArr;
size = src.size; = b
pArr = new int[size];
for(int i = 0; i < size; i++)
a
pArr[i] = src.pArr[i];
}
return *this;
}
Inside the method, this is the pointer containing the address of the
21
object calling that method
ASSIGNMENT OPERATOR
In the class inheritance, firstly call the
operator ‘=’ of base class
class MyIntArray : public Base{
private:
int *pArr; int size;
public:
MyIntArray& operator=(const MyIntArray&);
//…
};
MyIntArray& MyIntArray::operator=(const MyIntArray& src){
if(this != &src){
Base::operator=(src);
delete []pArr;
size = src.size;
pArr = new int[size];
for(int i = 0; i < size; i++) pArr[i] = src.pArr[i];
}
return *this;
} 22
ASSIGNMENT OPERATOR
Can define the operators ‘>>’ or ‘<<’ in the file ‘.h’/‘cpp’
combined with keyword ‘friend’ (means these operators is a
friend of class)
Syntax of unary operators (prefix or suffix): Return-type
ClassName::operator@()
◦ @: notation standing for the operator, such as ++ or –
◦ This operator has no input-parameter
+ Using unary
- or binary
* operator
/ depending
% on the ^problems &
| ~ ! = < > +=
-= *= /= %= ^= &= |=
<< >> >>= <<= == != <=
>= && || ++ -- ->* ,
-> [] () new new[] delete delete[]
23
ASSIGNMENT OPERATOR
Example: consider PhanSo
class PhanSo{
int tu, mau;
public:
PhanSo();
PhanSo(int, int);
PhanSo& operator+=(const PhanSo&);
PhanSo operator+(const PhanSo&);
bool operator==(const PhanSo&);
PhanSo& operator++();//++ prefix
PhanSo operator++(int);//++ suffix
friend ostream& operator<<(ostream&, const
PhanSo&);
//… 24
ASSIGNMENT OPERATOR
Example: consider PhanSo
PhanSo& operator+=(const PhanSo& src){ PhanSo& operator++(){//++ prefix
tu = tu*src.mau + mau*src.tu; tu+=mau;
mau = mau*src.mau; return (*this);
return *this; }
} PhanSo operator++(int){//++ suffix
PhanSo operator+(const PhanSo& src){ PhanSo tmp = *this;
PhanSo tmp = (*this); ++(*this);
tmp+=src; return tmp;
return tmp; }
}
bool operator==(const PhanSo& src){ void main(){
return ((tu == src.tu) && (mau == src.mau)); PhanSo a(1, 3), b(2, 5), c = a + b;
} cout << c << endl; // 11/15
cout << ++c << endl; // (11+15)/15
a += b;
cout << a << endl; // 11/15
cout << b++ << endl; // 2/5
cout << b << endl; // (2+5)/5
} 25
ASSIGNMENT OPERATOR
Some conventions/advices:
◦ Only overload the operator when the program is more natural
◦ Assure the operator is reasonable, for example: cannot overload the
operator ‘+’ of fraction with the subtraction inside
◦ Only overload the operator when it is significant, for example:
cannot multiply two DAYS
◦ Assure the consistency for the pairs of operators, for example ==/!=,
>/<…
◦ Some objects with large size use “const” to improve efficiency
◦ Implement the operators using private members inside the class
◦ Some symmetric binary operators should use “friend” to implement
outside the class
◦ Some operators needing left value, such as operator=, operator[],
operator(), operator->, operator*= or operator++ must be
implemented inside the class as non-static method
◦ Use operator() to access the multi-dimensional array’s members 26
COMPARISON WITH C# & JAVA
C++ supports operator overloading with normal, static or
virtual methods, but in C# operator overloading must be static
one
C# does not allow to overload operator=
A number of overloadable operators of C++ is larger than C#’s
In C#, once overloading binary operator+, operator+= also is
auto-overloaded
class PhanSo {
int tu, mau;
public static PhanSo operator+(PhanSo x, PhanSo y){
PhanSo tmp = new PhanSo();
tmp.tu = tmp.tu*src.mau + tmp.mau*src.tu;
tmp.mau = tmp.mau*src.mau;
return tmp;
}
// other methods
}; 27
COMPARISON WITH C# & JAVA
Java does not supports operator
overloading, except String class
In Java, objects is processed with
reference type. For example, operator= or
operator== will assign and compare
between the reference variables, but not in
the memory they point to.
With the objects of discrete datatype, Java
supports available operators similar to
built-in datatype in C++
28
PARAMETER PROBLEMS
Similarto structural variables, the object has the
same parameter-passing mechanism:
◦ Pass-by-value
◦ Pass-by-reference
◦ Pass-by-address (pass-by-pointer)
Pass-by-value: the compiler creates the copy of the
object passed in
Pass-by-reference: the compiler creates an ‘alias’ of
the object passed in
Pass-by-address: depending on pass-by-value or
pass-by-reference, the compiler will process the
same as pass-by-value or pass-by-reference
29
Passing by value an instance of a class makes copy-constructor run
PARAMETER PROBLEMS
(Pass-by-value)
Syntax:
◦ Return-type methodName(Datatype parameterName)
◦ Ex: int doSth(int a, int b, float c, Date d);
Analysis:
◦ Variables a, b, c, d: formal arguments
◦ Outside variables used to call and pass into them are called actual
arguments
◦ When a caller calls the method, formal arguments are set up a separate
memory and passed
#include the value from
<iostream> actual
void arguments
main() { of caller
using namespace std; int n = 10;
<50> // Sum 1 + 2 + … + n cout << tinhTong(n) << endl;
n10 long tinhTong(int x) { }
long tong = 0;
while (x > 0) {
Notes of pass-by-value:
<70> tong = tong + x; --x; 1) Needs separate memory & copy
648290173
10 } operations
x5 return tong; 2) Can pass a constant or expression
} 30
Notes of
pass-by-
referenc PARAMETER PROBLEMS
e:
1) Need (Pass-by-reference)
not Syntax:
separat
e ◦ Return-type methodName(Datatype& parameterName)
memory
& copy ◦ Ex: int doSth(int& a, int& b, float& c, Date& d);
operati Analysis: when a caller calls the method, formal
ons
2) arguments uses the same memory as actual arguments
Cannot of caller
pass a
constan #include <iostream> <20> <30>
t or using namespace std; 5
10 5
10
void swapInt(int& a, int& b) { int temp = a; a = b; b = temp; } x y
expressi
on void main() {
int x = 5, y = 10; <???> <???>
cout << “Before swap: x = ” << x << “, y = ” << y << endl; <20> <30>
swapInt(x, y); a b
cout << “After swap: x = ” << x << “, y = ” << y << endl;
}
31
PARAMETER PROBLEMS
(Pass-by-address)
A pointer has a memory of it owns
containing the address of the memory it is
pointing to <50> <60> <???>
void controThamTri(int* p) { *p = 5; p = new int; } 539 <50>
<90> <60>
a pT q
void controThamChieu(int* &q) {
q = new int[3];
<80> <70>
q[0] = 10; q[1] = 7; q[2] = 4;
} <50>
<80>
p
void main() {
int a = 9, *pT = &a; <90> 10
*pT = 3;
cout << “(0) a = ” << a << endl; 7
cout << “(1) Con tro pT = ” << pT << “, gia tri *pT = ” << *pT << endl; 4
controThamTri(pT);
cout << “(2) Con tro pT = ” << pT << “, gia tri *pT = ” << *pT << endl;
controThamChieu(pT);
cout << “(3) Con tro pT = ” << pT << “, gia tri *pT = ” << *pT << endl;
cout << “, ” << pT[1] << “, ” << pT[2] << endl;
delete[] pT;
} 32
PARAMETER PROBLEMS
(Default parameter)
May set the default values for parameters
◦ Ex: int doSomething(float a, int b =5);
int doSomething(float a, int b = 5) { //… }
void main() {
int x = 9;
doSomething(x); // b = 5
}
Note: creating default parameter follows
from right to left
◦ Ex: int doSomething(int a = 3, int b); // wrong
33
PARAMETER PROBLEMS
(Variable arguments)
May create a function without knowing a number of parameters
◦ Ex: float Avg(1, 2) 1.5
float avg(1, 2, 3) 2
Syntax: datatype methodName(datatype v1, …)
void nhieuThamSo(int n, …) {
va_list dsThamSo; va_start(dsThamSo, n);
cout << “So luong tham so: ” << n << endl;
for(int i = 0; i < n; i++) {
int a = va_arg(dsThamSo, int);
cout << “Tham so ” << i + 1 << “ = ” << a << endl;
}
va_end(dsThamSo);
}
void main() {
int x = 3, k = 5, h = 7, z = 10;
nhieuThamSo(4, x, k, h, z); nhieuThamSo(2, x, z);
} 34
COMPARISON WITH C# & JAVA
C#: transmitting a class variable to a
function can use pointer–like or pass-by-
reference mechanism
<200>
class PhanSo { 31 2
public int ts, ms;
<100>
public PhanSo(int t, int m) {
ts = t; ms = m; q <200>
}
};
class MainProgram { <300>
static void Inc(PhanSo p) { p.ts += p.ms; }
static void Main(){ p <200>
PhanSo q = new PhanSo(1, 2);
Inc(q);
}
}; 35
COMPARISON WITH C# & JAVA
C#: transmitting a class variable to a
function can use pass-by-address-value
and pass-by-reference mechanisms
<200>
class PhanSo {
public int ts, ms;
1 2
public PhanSo(int t, int m) {
ts = t; ms = m;
} <100>
}; <400>
<200>
class MainProgram { q <600> 3 7
static void Change(PhanSo p) { p = new PhanSo(3, 7); }
static void Change(ref PhanSo p) { p = new PhanSo(3, 7); } <300>
static void Main(){ <600>
PhanSo q = new PhanSo(1, 2); <400>
<200>
p
Change(q); 3 7
Change(ref q); <500>
}
}; p <100> 36
COMPARISON WITH C# & JAVA
C#: also supports variable arguments
class MainProgram {
public static void PrintData(params object[] list) {
for(int i = 0; i < list.Length; i++)
Console.WriteLine((object)list[i]);
Console.WriteLine();
}
static void Main(){ PrintData(1, ‘a’, “Test”, 7.5,
‘Z’); }
};
C#: support “out” keyword for variable
only receiving the result
class MainProgram {
public static void Test(out int x) { x = 1; }
static void Main(){ int a; Test(out a); }
};
37
COMPARISON WITH C# & JAVA
Java:
◦ Uses pass-by-value with
primitive datatype including
String class
◦ Use pass-by-reference with
Array
◦ Use pass-by-address-value with
class object
38
PARAMETER PROBLEMS
Example: consider the case of PhanSo
class PhanSo{
int tu, mau;
public:
PhanSo(int, int);
void Update(int, int);
friend ostream& operator<<(ostream& os, const PhanSo&);
};
PhanSo::PhanSo(int t, int m) {
tu = t; mau = m;
}
void PhanSo::Update(int t, int m) {
tu = t; mau = m;
}
ostream& operator<<(ostream& os, const PhanSo& ps) {
os << ps.tu << "/" << ps.mau << endl;
return os;
}
39
PARAMETER PROBLEMS
Example: consider PhanSo
void ThayDoiThamTri(PhanSo q) {q.Update(10, 10);}
void ThayDoiThamChieu(PhanSo& q){q.Update(10, 10);}
void ThayDoiThamTriContro(PhanSo* q) {q->Update(10, 10);}
void ThayDoiThamChieuContro(PhanSo*& q) {q->Update(10, 10);}
void main() { <100>
PhanSo p(2, 3); p ={2, 3}
cout << p;
ThayDoiThamTri(p);
cout << p; q ={2, 3} Pass-by-value
ThayDoiThamChieu(p); <200>
cout << p; q ={2, 3} Pass-by-reference
//////////////////////////////////////
<100>
PhanSo* t = new PhanSo(2, 3);
<500> <500>
cout << *t;
ThayDoiThamTriContro(t); t {2, 3} q Pass-by-pointer-reference
cout << *t; <600>
ThayDoiThamChieuContro(t);
q Pass-by-pointer-value
cout << *t;
<700>
} 40
TYPE–CASTING
C++ supports two type-casting methods:
◦ Implicit casting
◦ Explicit casting
Static
Dynamic
C-style
Const
Re-interpret
Developer can:
◦ Use the constructor to type-cast
◦ Use the operator to type-cast
41
TYPE–CASTING (IMPLICITLY)
https://www.geeksforgeeks.org/type-conversion-in-c/
Example:
#include <iostream>
using namespace std;
void main() {
int x = 10; // integer x
char y = ‘a’; // character c
// y implicitly converted to int. ASCII
// value of 'a' is 97
x = x + y;
// x is implicitly converted to float
float z = x + 1.0;
cout << “x = ” << x << endl
<< “y = ” << y << endl
<< “z = ” << z << endl;
}
43
TYPE–CASTING (EXPLICITLY)
https://www.geeksforgeeks.org/type-conversion-in-c/
TYPE–CASTING (EXPLICITLY)
Static Cast: It is a compile time cast
◦ Simple example:
void main() {
float f = 3.5;
int b = static_cast<int>(f);
cout << b;
}
◦ Class example
int main()
class Int {
int x;
{ public:
1 Int obj(3); 2X
6 Int(int x_in = 0) : x{ x_in } {
3 string str = obj; cout << “Conversion Ctor called” << endl;
5 obj = 20; }
7 string str2 = static_cast<string>(obj); 48 operator string() {
9 obj = static_cast<Int>(30); cout << “Conversion Operator” << endl;
return 0; return to_string(x);
} }
}; 46
https://www.geeksforgeeks.org/static_cast-in-c-type-casting-operators/
TYPE–CASTING (EXPLICITLY)
Static Cast: It is a compile time cast
◦ Inheritance example:
#include <iostream> pr
using namespace std; ot
ec
te
class Base { }; d
an
class Derived : public Base { }; d
pr
iv
void main() { at
ea
Derived d1; re
n ot
Base* b2 = static_cast<Base*>(&d1); al
lo
} we
d
Dynamic Cast:
◦ Mainly used for safe down-casting at run time
◦ Works only polymorphic base class
BASE CLASS
Downcasting Upcasting
DERIVED DERIVED
CLASS 1 CLASS 2
48
TYPE–CASTING (EXPLICITLY)
https://www.geeksforgeeks.org/dynamic-_cast-in-cpp/
Dynamic Cast:
◦ Example without polymorphic class
class Base {
void print() { cout << “Base” << endl; }
};
class Derived1 : public Base {
void print() { cout << “Derived1” << endl; }
};
class Derived2 : public Base {
void print() { cout << “Derived2” << endl; }
};
void main() {
Derived1 d1;
COMPILE ERROR
Base* bp = dynamic_cast<Base*>(&d1);
Derived2* dp2 = dynamic_cast<Derived2*>(bp);
“downcasting from
if (dp2 == nullptr) cout << “null” << endl; non-polymorphic
} base class”
49
TYPE–CASTING (EXPLICITLY)
https://www.geeksforgeeks.org/dynamic-_cast-in-cpp/
Dynamic Cast:
◦ Polymorphic class example: print “not null”
class Base {
virtual void print() { cout << “Base” << endl; }
};
class Derived1 : public Base {
void print() { cout << “Derived1” << endl; }
};
class Derived2 : public Base {
void print() { cout << “Derived2” << endl; }
};
void main() {
Derived1 d1;
Base* bp = dynamic_cast<Base*>(&d1); upcasting
Derived1* dp1 = dynamic_cast<Derived1*>(bp); downcasting
if (dp1 == nullptr) cout << “null” << endl;
else cout << “not null” << endl;
}
50
TYPE–CASTING (EXPLICITLY)
https://www.geeksforgeeks.org/dynamic-_cast-in-cpp/
Dynamic Cast:
◦ Polymorphic class example: print “null”
class Base {
virtual void print() { cout << “Base” << endl; }
};
class Derived1 : public Base {
void print() { cout << “Derived1” << endl; }
};
class Derived2 : public Base {
void print() { cout << “Derived2” << endl; }
};
void main() {
Derived1 d1;
Base* bp = dynamic_cast<Base*>(&d1); upcasting
Derived2* dp2 = dynamic_cast<Derived2*>(bp); error downcasting
if (dp2 == nullptr) cout << “null” << endl;
else cout << “not null” << endl;
}
51
TYPE–CASTING (EXPLICITLY)
https://www.geeksforgeeks.org/dynamic-_cast-in-cpp/
Dynamic Cast:
◦ Polymorphic class example: print “null”
class Base {
virtual void print() { cout << “Base” << endl; }
};
class Derived1 : public Base {
void print() { cout << “Derived1” << endl; }
};
class Derived2 : public Base {
void print() { cout << “Derived2” << endl; }
};
void main() {
Derived1 d1;
Base* bp = dynamic_cast<Base*>(&d1); upcasting
Derived1* dp1 = dynamic_cast<Derived1*>(bp); downcasting
if (dp1 == nullptr) cout << “null” << endl;
else cout << “not null” << endl;
try { Derived2& r1 = dynamic_cast<Derived2&>(d1); } error casting
catch (std::exception& e) { cout << e.what() << endl; }
}
52
https://www.geeksforgeeks.org/const_cast-in-c-type-casting-operators/
TYPE–CASTING (EXPLICITLY)
Const-cast: cast away the variables’s
constness
◦ Change non-const class members inside a const
member function
class student { void main() {
int roll; student s(3);
public: cout << “Old roll: ” << s.getRoll() << endl;
student(int r) : roll(r) {} s.fun();
void fun() const { cout << “New roll: ” << s.getRoll() << endl;
(const_cast <student*> (this) )->roll = 5; }
}
int getRoll() { return roll; } Compiler changes from “const student*
}; const this” to “student* const this”
53
https://www.geeksforgeeks.org/const_cast-in-c-type-casting-operators/
TYPE–CASTING (EXPLICITLY)
Const-cast: cast away the variables’
constness
◦ Pass const data to a function that doesn’t
receive const
int fun(int* ptr) { normal pointer
return (*ptr + 10);
}
int main()
{
const int val = 10;
const int *ptr = &val;
int *ptr1 = const_cast <int *>(ptr);
cout << fun(ptr1);
return 0;
}
54
https://www.geeksforgeeks.org/const_cast-in-c-type-casting-operators/
TYPE–CASTING (EXPLICITLY)
Const-cast: cast away the variables’
constness
◦ Being an undefined behavior to modify a value
initially declared as const
int fun(int* ptr) { normal pointer
*ptr = (*ptr + 10);
return (*ptr);
}
If erase this “const” int main() {
keyword, program const int val = 10;
will print 20
const int *ptr = &val;
int *ptr1 = const_cast <int *>(ptr);
cout << fun(ptr1);
cout << val; Maybe print 10
return 0;
} 55
https://www.geeksforgeeks.org/const_cast-in-c-type-casting-operators/
TYPE–CASTING (EXPLICITLY)
Const-cast: cast away the variables’
constness
◦ Being safe because casting won’t happen if the
type of cast is not same as original object
int main()
{
int a1 = 40;
const int* b1 = &a1;
char* c1 = const_cast <char *> (b1); // compiler error
*c1 = 'A';
return 0;
}
56
https://www.geeksforgeeks.org/const_cast-in-c-type-casting-operators/
TYPE–CASTING (EXPLICITLY)
Const-cast: cast away the variables’
constness
◦ Cast away volatile attribute
int main() {
int a1 = 40;
const volatile int* b1 = &a1;
cout << “typeid of b1 ” << typeid(b1).name() << ‘\n’;
int* c1 = const_cast <int *> (b1);
cout << “typeid of c1 ” << typeid(c1).name() << ‘\n’;
}
57
TYPE–CASTING (EXPLICITLY)
Re-interpret cast: cast the object of this
class into the object of that class (Two
classes can be completely different)
class A{};
class B{};
void main(){
A* a = new A();
B* b = reinterpret_cast<B*>(a);
}
58
https://www.geeksforgeeks.org/reinterpret_cast-in-c-type-casting-operators/
TYPE–CASTING (EXPLICITLY)
Purpose of re-interpret cast:
◦ Typecast any pointer to any other data type
◦ Used when we want to work with bits
◦ Boolean value is converted into integer value
struct mystruct { int x, y; char c; bool b; };
void main() { <affd38> <affd3c> <affd40>
5
mystruct s; s.x = 5; s.y = 10; s.c = ‘a’; s.b = true;
int* p = reinterpret_cast<int*>(&s); s 10 a1
12 1 cout << sizeof(s) << endl;
2 cout << *p << endl;
x y c b
3 p++;
4 cout << *p << endl;
5 p++; p <affd3c>
<affd38>
<affd40>
6 char* ch = reinterpret_cast<char*>(p);
7 cout << *ch << endl; <affd40>
ch <affd41>
8 ch++;
9 bool* n = reinterpret_cast<bool*>(ch);
n <affd41>
X cout << *n << endl;
TYPE–CASTING (EXPLICITLY)
Purpose of re-interpret cast:
◦ Typecast any pointer to any other data type
◦ Used when we want to work with bits
◦ Boolean value is converted into integer value
void main() {
1 int* p = new int(65); <100>
2 char* ch = reinterpret_cast<char*>(p); A
65
3 cout << *p << endl; <200>
4 cout << *ch << endl; <100>
p
5 cout << p << endl;
<300>
6 cout << &p << endl; <100>
7 cout << ch << endl; ch
8 cout << (void*)&ch << endl;
9 cout << (void*)ch << endl;
} 60
TYPE–CASTING (CONSTRUCTOR)
In some cases, we can utilize the
constructor to support the type-casting
Example: class PhanSo
class PhanSo{
int tu, mau;
public:
PhanSo(int);
};
3 PhanSo::PhanSo(int t){
tu = t; mau = 1;
}
void main(){
1 int t = 5;
2 PhanSo p = t;
} 61
TYPE–CASTING (OPERATOR)
Buildthe type-casting operator for class
PhanSo class PhanSo{
int tu, mau;
public:
PhanSo(int, int);
operator int();
};
462 PhanSo::operator int(){
return tu/mau;
}
void main(){
PhanSo p(6, 2);
1 int t1 = p; Implicitly
3 int t2 = int(p);
Explicitly
5 int t3 = (int)p;
} 62
OTHER PROBLEMS
Some problems of data members
◦ Static members
◦ The members being the type of
different class
◦ Constant method
Singleton pattern
Class with the static methods
63
STATIC MEMBER
Circumstance: the need of using one data member
shared with all the objects
C++ supports variable/static method (class-level
member)
◦ Don’t rely on any objects
◦ Members are shared with all the objects
Syntax
◦ Declaration:
static <Data-type> Function-name(parameter-list);
static <Data-type> Variable-name;
◦ Definition:
<Data-type> ClassName::VariableName = …;
64
STATIC MEMBER
Example
class Test{
static int count;
public:
static int Show();
Test(){count++;}
~Test(){count--;};
};
int Test::Show(){
return count;
}
int Test::count = 0;
void main(){
Test a, b;
int cout<<Test::Show();
} 65
MEMBER OF CLASS TYPE
Consider two classes: DUONGTRON & DIEM
class DUONGTRON{
DIEM I;
float R;
public:
DUONGTRON(){cout<<“Create the circle”;};
~DUONGTRON{cout<<“Destroy the circle”;};
};
class DIEM{
float X, Y;
public:
DIEM(){cout<<“Create point”;};
~DIEM(){cout<<“Destroy point”;};
};
66
MEMBER OF CLASS TYPE
Consider DUONGTRON & DIEM
void main(){
DUONGTRON dt;
}
“Create point”
“Create circle”
“Destroy circle”
“Destroy point”
67
USING INTIALIZER
Some cases of data member (property):
◦ A constant
◦ A reference
◦ An object of another class without default
constructor
Using “initializer” to define the values
Syntax:
-A() A getInstance(){
+static getInstance(): A return _obj;
}
71
SINGLETON PATTERN
Singleton source code
class A{ - Always define constructor
static A* obj; - Do not use default constructor
A();
- Put constructor into private or
public:
static A* getInstance(); protected scope
}; - Variable called “obj” is assigned
A* A::obj = NULL; NULL
A::A(){//…} - Return “obj” variable when
A* A::getInstance(){
developer calls “getInstance()” static
if(!obj) obj = new A();
return obj; method
}
void main(){
A* a = A::getInstance();
} 72
SINGLETON PATTERN
Example: applying singleton
class A{ class SortAlg{
static A* obj; static SortAlg* obj;
A(); SortAlg();
void (*currentAlg)(float[], int);
public: public:
static A* getInstance(); static SortAlg* getInstance(void (*pAlg)(float[], int) = NULL);
static void InterchangeSort(float[], int);
//…sort algorithms
void Sort(float[], int);
}; };
A* A::obj = NULL; SortAlg* SortAlg::obj = NULL;
A::A(){//…} SortAlg::SortAlg(){currentAlg = InterchangeSort;}
A* A::getInstance(){ SortAlg* SortAlg::getInstance(void (*pAlg)(float[], int) = NULL){
if(!obj) obj = new A(); if(!obj) obj = new SortAlg();
if(pAlg != NULL) obj->currentAlg = pAlg;
return obj; return obj;
} }
void SortAlg::InterchangeSort(float a[], int n){//…}
void SortAlg::Sort(float a[], int n){
if(currentAlg != NULL) currentAlg(a, n);
}
73
SINGLETON PATTERN
Example: applying singleton
void main(){ void main(){
//Prepare data float a[] = {1.4F, -5.2F, 3.3F, 0}; int n = sizeof(a)/sizeof(a[0]);
A* a = A::getInstance(); SortAlg* a = SortAlg::getInstance();
//Use a to solve the problem a->Sort(a, n);
} }
Some limitation:
- Must provide a number of elements
- Compiler cannot detect if all members in array are not the same type77
UPDATES IN C++(USING {})
Using class “Initializer_list<T>” in a
constructor
class MyIntArray {
vector<int> Data;
<vector> defined copy constructor
public:
int size() { return Data.size(); }
void resize(int m) { Data.resize(m); }
MyIntArray(const initializer_list<int>& L) :Data{ L } {}
int& operator[](int i) { return Data.at(i); }
friend ostream& operator<<(ostream& out, MyIntArray& a) {
for (auto& x : a.Data) { out << x << “ ”; }
return out;
}
};
void main(){
MyIntArray b{ 1,4,5,6 }; cout << “b: ” << b << endl;
b = { 7,8,9,3 }; cout << “b: ” << b << endl;
}
78
Note: may declare MyIntArray b = {1, 4, 5, 6}
UPDATES IN C++(USING {})
2D-Array example with
“Initializer_list<T>”
typedef vector<int> IntVector; friend ostream& operator<<(ostream& out, IntArray2D& a) {
typedef initializer_list<int> IntInitializerList; for (int i = 0; i < a.xSize(); i++) {
class IntArray2D { for (int j = 0; j < a[i].size(); j++) out << a[i][j] << “ ”;
vector<IntVector> Data; out << endl;
public: }
int xSize() const { return Data.size(); } return out;
int ySize() const { return Data[0].size(); } }
IntVector& operator[](int i) { return Data.at(i); } void main(){
void resize(int m, int n) { IntArray2D A{ {1,2,3},{4,5,6},{7,8,9} };
if (m < 0) m = -m; if (n < 0) n = -n; cout << “m = ” << A.xSize() << “, n = ” << A.ySize() << endl;
Data.resize(m); cout << A;
for (auto& a : Data) { a.resize(n); } IntArray2D B(2, 2), C{3, 4};
} }
IntArray2D(int m, int n) { resize(m, n); }
IntArray2D(const initializer_list<IntInitializerList> & L2D) {
for (auto& L : L2D) { Data.push_back(L); } <vector> defined copy constructor
}
friend ostream& operator<<(ostream& out, IntArray2D& a);
};
79
UPDATES IN C++
(Implicit initializer_list parameter)
Method with vector<T>, where T is
defined (such as int or float), no need to
use initializer_list<T>
int findMaxInt(const vector<int>& a){ void main(){
int lc = a.front(); int m = findMaxInt({ 1,4,5,6 });
for(auto& v: a) { }
if(lc < v) lc = v;
}
<vector> defined copy constructor
return lc;
}
Similar to template method
template <class T> void main(){
T findMaxInt(const vector<T>& a){ int m = findMaxInt<int>({ 1,4,5,6 });
auto lc = a.front(); }
for(auto& v: a) { if(lc < v) lc = v; }
return lc;
} 80
UPDATES IN C++
(Implicit initializer_list parameter)
The class “MyIntArray” DOES NOT
USE initializer_list<int>
class MyIntArray { void main(){
vector<int> Data; MyIntArray b{ 1,4,5,6 }; // error compile
public: MyIntArray b({ 1,4,5,6 }); // Correct
int size() { return Data.size(); } b = { 7,8,9,3 }; // error compile
void resize(int m) { Data.resize(m); } b = vector<int>{ 7,8,9,3 }; // Correct
MyIntArray(const vector<int>& L) :Data{ L } {} }
int& operator[](int i) { return Data.at(i); }
friend ostream& operator<<(ostream& out, MyIntArray& a) {
for (auto& x : a.Data) { out << x << “ ”; }
return out;
}
};
81
UPDATES IN C++
(Implicit initializer_list parameter)
The class “IntArray2D” DOES NOT USE
initializer_list<int>
typedef vector<int> IntVector; friend ostream& operator<<(ostream& out, IntArray2D& a) {
//typedef initializer_list<int> IntInitializerList; for (int i = 0; i < a.xSize(); i++) {
class IntArray2D { for (int j = 0; j < a[i].size(); j++) out << a[i][j] << “ ”;
vector<IntVector> Data; out << endl;
public: }
int xSize() const { return Data.size(); } return out;
int ySize() const { return Data[0].size(); } }
IntVector& operator[](int i) { return Data.at(i); } void main(){
void resize(int m, int n) { IntArray2D A({ {1,2,3},{4,5,6},{7,8,9} });
if (m < 0) m = -m; if (n < 0) n = -n; cout << A;
Data.resize(m); A = IntArray2D({{4, 1, 2, 3}, {7, 4, 5, 6}, {6, 7, 8, 9}});
for (auto& a : Data) { a.resize(n); } cout << A;
} }
IntArray2D(int m, int n) { resize(m, n); }
IntArray2D(const vector<IntVector> & L2D) {
for (auto& L : L2D) { Data.push_back(L); }
}
friend ostream& operator<<(ostream& out, IntArray2D& a);
};
82
UPDATES IN C++
(Keyword ‘delete’)
“delete” is used to deallocate the memory
It can be used to disable the operators in
the class
class SomeClass {
Operator disabled disable operator
// Some properties
public:
void operator delete(void*) = delete;
void operator delete[](void*) = delete;
friend void ObjFree(SomeClass* pObj) {
// deallocate the memory…
}
// Some methods
};
The statement “delete pObj” is invalid
83
UPDATES IN C++
(Keyword ‘delete’)
Example of IntArray2D
typedef vector<int> IntVector; friend ostream& operator<<(ostream& out, IntArray2D& a) {
typedef initializer_list<int> IntInitializerList; for (int i = 0; i < a.xSize(); i++) {
class IntArray2D { for (int j = 0; j < a[i].size(); j++) out << a[i][j] << “ ”;
vector<IntVector> Data; out << endl;
public: }
int xSize() const { return Data.size(); } return out;
int ySize() const { return Data[0].size(); } }
IntVector& operator[](int i) { return Data.at(i); } void main(){
void resize(int m, int n) { IntArray2D A{ {1,2,3},{4,5,6},{7,8,9} }; // Correct
if (m < 0) m = -m; if (n < 0) n = -n; IntArray B; // Correct
Data.resize(m); IntArray2D B(2, 2), C{3, 4}; // Incorrect
for (auto& a : Data) { a.resize(n); } }
}
IntArray2D(){}; //IntArray2D(int m, int n) { resize(m, n); }
IntArray2D(int m, …) = delete; All constructors at least one
IntArray2D(const initializer_list<IntInitializerList> & L2D) { parameter are not allowed
for (auto& L : L2D) { Data.push_back(L); }
}
friend ostream& operator<<(ostream& out, IntArray2D& a);
};
84
UPDATES IN C++
(Keyword ‘default’)
“default”asks the compiler to generate
some default methods
Example of default constructor
◦ If user defines any constructor in class, default
constructor won’t be auto-generated
◦ Can write this default constructor or use
“default” keyword
class IntArray2D {
// …
IntArray2D() = default; // or IntArray2D(){}
// …
}; 85
UPDATES IN C++
(Move constructor)
Example of copy constructor
void main() {
class Move {
vector<Move> vec;
int* data;
vec.push_back(10); vec.push_back(20);
public:
} 1) Create “Hidden” Move object 10
4 1 Move(int d) { 2) Create the 1 Move object of vector
st
data = new int; *data = (*source.data); 3) Destroy “Hidden” Move object 10 (nullptr)
} 4) Create “Hidden” Move object 20
5) Create the 2 Move object of vector (Move constructor)
nd
data = source.data; source.data = nullptr; 7) Destroy the old 1 Move object of vector
st
if (data != nullptr) { cout << “Destructor is called for ” << *data << endl; }
else cout << “Destructor is called” << “ for nullptr” << endl;
delete data;
}
};
&& is a new reference operator defined in the C++11 standard. int&& a means “a” is an r-value reference87