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

01 CPP

Uploaded by

nttqn203
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)
33 views

01 CPP

Uploaded by

nttqn203
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/ 81

C++ Review

1
Outline
• Introduction
• Class/object
• Constructor & Destructor
• Function and Operator overloading
• Friend class
• Pointer & Reference
• Template
• Error handling
• Standard Template Library
Object-Oriented Programming in C++
• Object-Oriented Programming
– Encapsulation
– Abstraction
– Inheritance
– Polymorphism
• C++
– Improvement on C language
– Object-oriented programming
– Created by Bjarne Stroupstrup in 1985

3
Classes and Objects
• Class: a type definition that includes both
– data properties, and
– operations permitted on that data
• Object: a variable that
– is declared to be of some class
– therefore includes both data and operations for that
data
• Appropriate usage:
“A variable is an instance of a type.”
“An object is an instance of a class.”

4
Basic Class Syntax
• A class in C++ consists of its members.
– A member can be either data or function.
• The functions are called member functions
(or methods)
• Each instance of a class is an object.
– Each object contains the data components
specified in class.
– Methods/functions are used to act on an
object.
5
Class syntax - Example
// A class for simulating an integer memory cell

class IntCell
{
public:
IntCell( )
{ storedValue = 0; }
constructors
IntCell(int initialValue )
{ storedValue = initialValue;}

int read( )
{ return storedValue; }

void write( int x )


{ storedValue = x;}

private:
int storedValue;
};

6
Class Members
• Public member is visible to all routines and may
be accessed by any method in any class.
• Private member is not visible to non-class
routines and may be accessed only by methods in its
class.
• Typically,
– Data members are declared private
– Methods are made public
• Restricting access is known as information hiding.

7
Class Members

8
Constructors
• A constructor is a method that executes when an object of a
class is declared and sets the initial state of the new object.

• A constructor
– has the same name with the class,
– no return type
– has zero or more parameters
• The constructor without an argument is the default
constructor

• There may be more than one constructor defined for a class.

• If no constructor is explicitly defined, one that initializes the


data members using language defaults is automatically
generated.
9
Extra Constructor Syntax
// A class for simulating an integer memory cell

class IntCell
{
public: Single
IntCell( int initialValue = 0 ) constructor
: storedValue( initialValue) { } (instead of
two)
int read( ) const
{ return storedValue; }

void write( int x )


{ storedValue = x; }
private:
int storedValue;
};

10
Object Declaration

#include <iostream>
using namespace std;
#include "IntCell.h"

int main()
{
//correct declarations
IntCell m1;
IntCell m2 ( 12 );
IntCell *m3;

// incorrect declaration
Intcell m4(); // this is a function declaration,
// not an object

11
Object use in driver program
// program continues

m1.write(44);
m2.write(m2.read() +1);
cout << m1.read() << " " << m2.read() << endl;
m3 = new IntCell;
cout << "m3 = " << m3->read() << endl;
delete m3;
return 0;
}

12
Example: Class Time
class Time {
public:
Time( int = 0, int = 0, int = 0 ); //default
//constructor
void setTime( int, int, int ); //set hr, min,sec
void printMilitary(); // print am/pm format
void printStandard(); // print standard format

private:
int hour;
int minute;
int second;
};

13
Declaring Time Objects
// Note that implementation of class Time not given
// here.

int main(){
Time t1, // all arguments defaulted
t2(2), // min. and sec. defaulted
t3(21, 34), // second defaulted
t4(12, 25, 42); // all values specified
. . .
}

14
Class Interface and Implementation
• In C++, separating the class interface from its
implementation is common.
– The interface remains the same for a long time.
– The implementations can be modified independently.
– The writers of other classes and modules have to know
the interfaces of classes only.
• The interface lists the class and its members (data
and function prototypes) and describes what can be
done to an object.
• The implementation is the C++ code for the
member functions.
15
Separation of Interface and Implementation
• It is a good programming practice for large-scale
projects to put the interface and implementation
of classes in different files.
• For small amount of coding it may not matter.
• Header File: contains the interface of a class.
Usually ends with .h (an include file)
• Source-code file: contains the implementation of a
class. Usually ends with .cpp (.cc or .C)
• .cpp file includes the .h file with the preprocessor command
#include.
» Example: #include ”myclass.h”

16
Separation of Interface and Implementation

• A big complicated project will have files that


contain other files.
– There is a danger that an include file (.h file) might be
read more than once during the compilation process.
• It should be read only once to let the compiler learn the
definition of the classes.
• To prevent a .h file to be read multiple times, we
use preprocessor commands #ifndef and
#define in the following way.

17
Class Interface
#ifndef _IntCell_H_
#define _IntCell_H_

class IntCell
{
public:
IntCell( int initialValue = 0 );
int read( ) const;
void write( int x );
private:
int storedValue;
};
#endif
IntCell class Interface in the file IntCell.h

18
Class Implementation
#include <iostream>
#include “IntCell.h”
using std::cout;

//Construct the IntCell with initialValue


IntCell::IntCell( int initialValue)
: storedValue( initialValue) {}

//Return the stored value.


int IntCell::read( ) const
{ Scope operator:
return storedValue;
} ClassName :: member
//Store x.
void IntCell::write( int x )
{
storedValue = x;
}
IntCell class implementation in file IntCell.cpp
19
A driver program
#include <iostream>
#include “IntCell.h”
using std::cout;
using std::endl;

int main()
{
IntCell m; // or IntCell m(0);

m.write (5);
cout << “Cell content : “ << m.read() << endl;

return 0;
}

A program that uses IntCell in file TestIntCell.cpp

20
Destructors
• Member function of class
• Performs termination housekeeping before the
system reclaims the object’s memory
• Complement of the constructor
• Name is tilde (~) followed by the class name
• E.g. ~IntCell( );
~Time( );
• Receives no parameters, returns no value
• One destructor per class

21
Destructors
• A destructor is a special member function of a
class that is executed whenever an object of it's
class goes out of scope
• Free automatically the allocated memory (using
delete operator)

22
Destructor Example
class IntCell{
public:
IntCell(int initialValue=0)
{ storedValue = new int (initialValue);}

~IntCell()
{ delete storedValue; }

int read( ) const


{ return *storedValue; }

void write( int x ) { *storedValue = x; }


private:
int *storedValue;
}
23
Destructor Example

24
Accessor and Modifier Functions

• A method that examines but does not


change the state of its object is an accessor.
– Accessor function headings end with the word
const
– For example, the getter functions
• A member function that changes the state
of an object is a mutator.
– For example, the setter functions

25
Another Example: Complex Class
#ifndef _Complex_H
#define _Complex_H

using namespace std;


class Complex
{ // by default private
float re, im; // real part & imaginary part
public:
Complex(float x = 0, float y = 0)
: re(x), im(y) { }

Complex operator*(Complex rhs) const;


float modulus() const;
void print() const;
};

#endif

Complex class Interface in the file Complex.h 26


Implementation of Complex Class
#include <iostream>
#include <cmath>
#include "Complex.h"
Complex Complex::operator*(Complex rhs) const
{
Complex prod;
prod.re = (re*rhs.re - im*rhs.im);
prod.im = (re*rhs.im + im*rhs.re);
return prod;
}
float Complex::modulus() const
{
return sqrt(re*re + im*im);
}
void Complex::print() const
{
std::cout << "(" << re <<"," << im << ")" << std::endl;
}

Complex class implementation in file Complex.cpp 27


Using the class in a Driver File
#include <iostream>
#include "Complex.h"
int main()
{
Complex c1, c2(1), c3(1,2);
float x;
// overloaded * operator!!
c1 = c2 * c3 * c2;

// mistake! The compiler will stop here, since the


// Re and Imag parts are private.
x = sqrt(c1.re*c1.re + c1.im*c1.im);

// OK. Now we use an authorized public function


x = c1.modulus();

c1.print();
return 0;
}
28
A program that uses Complex in file TestComplex.cpp
Function Overloading
• Function overloading:
– Functions with same name and different parameters
– Overloaded functions performs similar tasks
• Function to square ints and function to square floats
int square( int x) {return x * x;}
float square(float x) { return x * x; }
– Program chooses function by signature
• Signature determined by function name and parameter types
• Type safe linkage - ensures proper overloaded function called

29
Function Overloading
• Function overloading:
– Functions with same name and different parameters
– Overloaded functions performs similar tasks

– Program chooses function by signature


• Signature determined by function name and parameter types
30
// Using overloaded functions
#include <iostream>
using std::cout;
using std::endl;
int square( int x ) { return x * x; }
double square( double y ) { return y * y; }

int main()
{
cout << "The square of integer 7 is " << square( 7 )
<< "\nThe square of double 7.5 is " << square( 7.5 )
<< endl;

return 0;
}

31
Overloaded Operators
• An operator with more than one meaning is said to
be overloaded.
2 + 3 3.1 + 3.2 è + is an overloaded operator

• To enable a particular operator to operate correctly


on instances of a class, we may define a new
meaning for the operator.
è we may overload it

Ex: operator* from Complex and Vector classes

32
Operator Overloading
• Format
– Write function definition as normal
– Function name is keyword operator followed by the
symbol for the operator being overloaded.
– operator+ would be used to overload the addition
operator (+)
• No new operators can be created
– Use only existing operators
• Built-in types
– You cannot change how two integers are added

33
Overloaded Operators -- Example
What if we want to multiply a complex number with a scalar?
Define another function with the same name but different
parameters.

class Complex
{
...

Complex operator*(Complex rhs) const;


Complex operator*(float k) const;

...
};

34
Implementation of Complex Class
Complex Complex::operator*(Complex rhs) const
{
Complex prod;
prod.re = (re*rhs.re - im*rhs.im);
prod.im = (re*rhs.im + im*rhs.re);
return prod;
}

Complex Complex::operator*(float k) const


{
Complex prod;
prod.re = re * k;
prod.im = im * k;
return prod;
}

Complex class implementation in file Complex.cpp 35


Using the class in a Driver File
#include <iostream>
#include "Complex.h"

int main()
{
Complex c1, c2(1), c3(1,2);

c1 = c2 * c3 * c2;
c1.print();
c1 = c1 * 5; // translated to c1.operator*(5)
c1.print();

return 0;
}

36
A program that uses Complex in file TestComplex.cpp
Friend Classes
A class may declare another class as a friend as well. In that case all
member functions of the “befriended” class can access the private
members of its friend class
class A
{
...
};

class B
{
...
friend A;
};
“A” can access private members of “B” (but not vice versa!)

37
Pointers
• Normal variables contain a specific value (direct reference)
int count = 7;

• Pointer variables contain memory addresses as their


values
int * countPtr;
countPtr = & count;

38
Pointer Operators
• & (address operator) - Returns the address of operand
int y = 5;
int *yPtr;
yPtr = &y; // yPtr gets address of y
– yPtr “points to” y

• * (indirection/dereferencing operator)
– Returns an alias of what its operand points to
– *yptr returns y (because yptr points to y)
– * can be used for assignment
*yptr = 7; // changes y to 7

39
Passing parameters to functions by value
void SetToZero (int var)
{
var = 0;
}

• You would make the following call:

SetToZero(x);

• This function has no effect whatever to change the value of x.


• This is referred to as call-by-value.

40
Passing parameters by reference
void SetToZero (int *ip)
{
*ip = 0;
}

• You would make the following call:

SetToZero(&x);

This is referred to as call-by-reference.

41
/* Swapping arguments (incorrect version) */
#include <iostream>

void swap (int p, int q)


{
int tmp;

tmp = p;
p = q;
q = tmp;
}

int main (void)


{
int a = 3;
int b = 7;
cout << a << b << endl;
swap(a,b);
cout << a << b << endl;
return 0;
}
42
/* Swapping arguments (correct version) */
#include <iostream>

void swap (int *p, int *q)


{
int tmp;

tmp = *p; p q
*p = *q;
*q = tmp;
}

int main (void)


{ a b
int a = 3; 3 7
int b = 7;
cout << a << b << endl;
swap(&a, &b);
cout << a << b << endl;
return 0;
}
43
References
• References are a type of C++ variable that act
as an alias to another variable.
• A reference variable acts just like the original
variable it is referencing.
• References are declared by using an
ampersand (&) between the reference type
and the variable name.

44
Example
int n = 5, m = 6; You cannot declare a
int &rn = n; reference without
giving a value.
n = 6;
rn = 7,
cout << n << rn << m << endl;
rn = m ;
cout << n << rn << m << endl;

45
/* Swapping arguments - with reference variables*/
#include <iostream>

void swap (int &p, int &q)


{
int tmp;

tmp = p; p q
p = q;
q = tmp;
}
int main (void)
{ a b
int a = 3; 3 7
int b = 7;
cout << a << b << endl;
swap(a, b);
cout << a << b << endl;
return 0;
}

46
Dynamic Memory Allocation
• new and delete
– new - automatically creates object of proper size, calls
constructor, returns pointer of the correct type
– delete - destroys object and frees space
– You can use them in a similar way to malloc and free in C.
• Syntax:
– TypeName *typeNamePtr;
– typeNamePtr = new TypeName;
– new creates TypeName object, returns pointer (which typeNamePtr
is set equal to)
– delete typeNamePtr;
– Calls destructor for TypeName object and frees memory

47
Example
// declare a ptr to user-defined data type
IntCell *ptr1;
int *ptr2;

// dynamically allocate space for an IntCell;


// initialize values; return pointer and assign
// to ptr1
ptr1 = new IntCell(5);
// dynamiccaly allocate an array of 12 numbers
ptr2 = new int[2];

// free up the memory


delete ptr1;
delete [] ptr2;

48
const Reference
• A const reference will not let you change the
value it references:
• Example:
int n = 5;
const int & rn = n;

rn = 6; // error!!

• const reference is like a const pointer to a


const object.

49
References vs. Pointers
Everything that is accomplished by references can
be accomplished by pointers but the syntax of
references is simpler
Example
int n= 5;
int &rn = n;
int *const p = &n;
*p = 6;
Same effect
rn = 6;

50
Pointers and const
There are two different ways that pointers and
const can be intermixed:
1. Constant pointer
2. Pointer to a constant variable

51
Constant Pointer
• A const pointer must be initialized to a value
upon declaration, and its value can not be
changed.
• However, because the value being pointed to is
still non-const, it is possible to change the value
being pointed to via dereferencing the pointer:

int *const p = &i;


*p = 6; // it is O.K.
p = &j; // NOT O.K.
52
Pointer to a const variable
• It is also possible to declare a pointer to a constant
variable by using the const before the data type:
int i;
const int * p = &i;
*p = 6; // it is NOT O.K., because i is
//treated as constant when accessed by p.
• However, it can be changed independently:
i = 6; // It is O.K.
• It is also possible to declare a const pointer to a
constant value:
const int n = 5;
const int * const p = &n;
53
Parameter Passing
In C, all parameters are passed by value (call by value).
But C++ offers three options:
• Call by value
– Copy of data passed to function
– Changes to copy do not change original
• Call by reference
– Uses &
– Avoids a copy and allows changes to the original
• Call by constant reference
– Uses const&
– Avoids a copy and guarantees that actual parameter will not
be changed

54
Example
#include <iostream>
using std::cout;
using std::endl;

int squareByValue( int ); // pass by value


void squareByReference( int & ); // pass by reference
int squareByConstReference ( const int & ); // const ref.

int main()
{ int x = 2, z = 4, r1, r2;

r1 = squareByValue(x);
squareByReference( z );
r2 = squareByConstReference(x);

cout << "x = " << x << " z = “ << z << endl;
cout << “r1 = " << r1 << " r2 = " << r2 << endl;
return 0;
}
55
Example (cont.)
int squareByValue( int a )
{
return a *= a; // caller's argument not modified
}
void squareByReference( int &cRef )
{
cRef *= cRef; // caller's argument modified
}
int squareByConstReference (const int& a )
{
// a *= a; not allowed (compiler error)
return a * a;
}

56
The uses of keyword const
We may encounter const in the following cases:
1. Const reference parameter:
Complex operator*(const Complex& rhs) const;
In this case it means the parameter cannot be modified.

2. Const member function:


Complex operator*(const Complex& rhs) const;

In this case it means the function cannot modify class members.

3. Const object/variable:

const Complex c1(3, 4);

In this case it means the object cannot be modified.


57
Improving the Complex Class
#ifndef _Complex_H
Old class:
#define _Complex_H

using namespace std;


class Complex
{
float re, im; // by default private
public:
Complex(float x = 0, float y = 0)
: re(x), im(y) { }

Complex operator*(const Complex& rhs) const;


float modulus() const;
void print() const;
};

#endif

Complex class Interface in the file Complex.h 58


Improving the Complex Class
#include <iostream>
#include <cmath>
#include "Complex.h"

Complex Complex::operator*(const Complex& rhs) const


{
Complex prod;
prod.re = (re*rhs.re - im*rhs.im);
prod.im = (re*rhs.im + im*rhs.re);
return prod;
}
float Complex::modulus() const
{
return sqrt(re*re + im*im);
}
void Complex::print() const
{
std::cout << "(" << re <<"," << im << ")" <<
std::endl;
}
59
Complex class implementation in file Complex.cpp
this Pointer
• Each class object has a pointer which
automatically points to itself. The pointer is
identified by the keyword this.
• Another way to think of this is that each member
function (but not friends) has an implicit first
parameter; that parameter is this, the pointer
to the object calling that function.

60
Example: overloading operator=
// defining an overloaded assignment operator
Complex & Complex :: operator=(const Complex & rhs )
{
// don't assign to yourself!
if ( this != &rhs ) // note the "address of" rhs
// why?
{
this -> Re = rhs.Re; // correct but
//redundant: means Re = rhs.Re
this -> Imag = rhs.Imag;
}
return *this; // return the calling class object
// enables cascading
}

61
Example
MyString& MyString::operator=(const MyString& rhs)
{
if (this != &rhs) {
delete[] this->str;
// donate back useless memory

this->length = rhs.length;

// allocate new memory


this->str = new char[this->length + 1];

strcpy(this->str, rhs.str); // copy characters


}
return *this; // return self-reference
}

62
Templates
• The template allows us to write routines
that work for arbitrary types without
having to know what these types will be.

• Two types:
– Function templates
– Class templates

63
Function Templates
• A function template is not an actual function;
instead it is a design (or pattern) for a function.
• The compiler creates the actual function based on
the actual types used in the program.
// swap function template.

template < class T>


void swap( T &lhs, T &rhs )
{
T tmp = lhs;
lhs = rhs;
rhs = tmp;
}

The swap function template


64
Using a template
• Instantiation of a template with a particular type, logically
creates a new function.
• Only one instantiation is created for each parameter-type
combination.
int main()
{ int x = 5, y = 7;
double a = 2, b = 4;
swap(x,y); //instanties an int version of swap
swap(x,y); //uses the same instantiation
swap(a,b); //instantiates a double version of swap

cout << x << “ “ << y << endl;


cout << a << “ “ << b << endl;
// swap(x, b);
// Illegal: no match
return 0;
}
65
Class templates
• Class templates are used to define generic classes:
– e.g. it may be possible to use a class that defines several operations on a
collection of integers to manipulate a collection of real numbers.

template <class T>


class TemplateTest
{
// this class can use T as a generic type
public:
void f(T a);
T g();
...
private:
T x, y, z;
...
};

66
Implementation
• Each member function must be declared as a template.
• All member functions must be implemented in the header
file (so that the compiler can find their definition and
replace “T” with the actual parameter type)

// Typical member implementation.


template <class T>
void TemplateTest<T>::f(T a)
{
// Member body
}

67
Object declarations using template classes

Form:
class-name <type> an-object;
Interpretation:
– Type may be any defined data type. Class-name
is the name of a template class. The object
an-object is created when the arguments
specified between < > replace their
corresponding parameters in the template
class.

68
Example
// Memory cell interface (MemoryCell.h)

template <class T>


class MemoryCell
{
public:
MemoryCell(const T& initVal = T());
const T& read( ) const;
void write(const T& x);

private:
T storedValue;
};

69
Class template implementation
// Implementation of class members

template <class T>


MemoryCell<T>::MemoryCell(const T& initVal) :
storedValue(initVal){ }

template <class T>


const T& MemoryCell<T>::read() const
{
return storedValue;
}

template <class T>


void MemoryCell<T>::write(const T& x)
{
storedValue = x;
}
70
A simple test routine
int main()
{
MemoryCell<int> m; // instantiate int version
MemoryCell<float> f; // instantiate float ver.
MemoryCell<int> m2; // use the previously created
class

m.write(5);
m2.write(6);
f.write(3.5);
cout << “Cell content: ” << m.read() << endl;
cout << “Cell content: ” << m2.read() << endl;
cout << “Cell content: ” << f.read() << endl;
return 0;
}

71
C++ Error Handling
• In C, errors are reported by returning error codes from
functions:
int read(const char* filename, char data[])
{
FILE* fp = fopen(filename, “r”);
if (fp == NULL)
return -1; // indicate error

// read file contents into data


...
}

72
C++ Error Handling
• In C++, we have a more advanced mechanism called
exceptions
• It uses three keywords: throw, catch, try
• The function that encounters an error throws an exception:

int read(const char* filename, char data[])


{
FILE* fp = fopen(filename, “r”);
if (fp == NULL)
throw “file open error”; // indicate error

// read file contents into data


...
}

73
C++ Error Handling
• This exception must be caught, otherwise the program will
abnormally terminate:
int main()
{
char data[128];
try {
read(“test.txt”, data);
... // some other code
}
catch(const char* error) {
// if read throws an exception,
// program will continue executing from here
cout << “Error message:” << error << endl;
}
}
74
C++ Error Handling
• Note that we throw an object or a variable, and we
catch an object or a variable. These types should
match for the exception to be caught
• In the previous example we threw a const char*
and caught a const char*, so it was correct

75
Another Example
• We can also throw an object of a user defined class:
class FileReadError
{
};

int read(const char* filename, char data[])


{
FILE* fp = fopen(filename, “r”);
if (fp == NULL)
throw FileReadError(); // indicate error

// read file contents into data


...
}

76
C++ Error Handling
• Then we must update the catch code as well:

int main()
{
char data[128];
try {
read(”test.txt”, data);
}
catch(FileReadError error) {
// if read throws an exception,
// we will come here
}
}

77
Standard Template Library
• I/O Facilities: iostream
• Garbage-collected String class
• Containers
– vector, list, queue, stack, map, set
• Numerical
– complex
• General algorithms
– search, sort
78
Using the vector
• Vector: Dynamically growing, shrinking array of elements
• To use it include library header file:
#include <vector>
• Vectors are declared as
vector<int> a(4); //a vector called a,
//containing four integers
vector<int> b(4, 3); //a vector of four
// elements, each initialized to 3
vector<int> c; // 0 int objects
• The elements of an integer vector behave just like ordinary
integer variables
a[2] = 45;

79
Manipulating vectors
• The size() member function returns the
number of elements in the vector.
a.size() returns a value of 4.
• The = operator can be used to assign one
vector to another.
• e.g. v1 = v2, so long as they are vectors of
the same type.
• The push_back() member function allows
you to add elements to the end of a vector.
80
push_back() and pop_back()

vector<int> v;
v.push_back(3);
v.push_back(2);
// v[0] is 3, v[1] is 2, v.size() is 2
v.pop_back();
int t = v[v.size()-1]; //t=3
v.pop_back();

81

You might also like