0% found this document useful (0 votes)
14 views42 pages

3. Programming in C++

The document provides an overview of C++ programming, focusing on data structures, classes, and object-oriented programming concepts. It covers primitive and composite data types, class definitions, member functions, constructors, destructors, and the use of templates for creating versatile data structures. Additionally, it includes examples of class implementation and usage in C++.
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)
14 views42 pages

3. Programming in C++

The document provides an overview of C++ programming, focusing on data structures, classes, and object-oriented programming concepts. It covers primitive and composite data types, class definitions, member functions, constructors, destructors, and the use of templates for creating versatile data structures. Additionally, it includes examples of class implementation and usage in C++.
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/ 42

C++ Programming

CSE225: Data Structures and Algorithms


The Hello Program
#include <iostream>
using namespace std;

int main()
{
char name[100];
cout << "Enter your name: ";
cin >> name; //scanf
cout << "Hello " <<name<<endl; //printf
return 0;
}
C++ has two types of data types:

1. Primitive Data Type:


- Basic Unit of Language
- Each Primitive value is a single datum
Example: int , char, float, etc.

• 2. Composite Data Type:


- Multiple pieces of related data as a single datum
Example: array, structure, class, etc.

** What are the differences between Primitive and Composite Data Types??
Structure
- A linear, direct access data structure with heterogeneous
components
- A component is also called a field or a member
- Each field has its own type
- An identifier is used to name a field/component

Example:

struct CarType {
int year;
char maker[10];
float price;
};
CarType MyCar;//in C++ CarType is considered a data type
//name; unlike C where you have to write struct CarType
Objects & Class

• Object:
• a variable or an instance of a class

OBJECT
set of methods
Operations (public member functions)

Data
internal state
(values of private data members)
Motivation for classes
• Object-Oriented Programming (OOP)
• Package together a set of related data and operations
(encapsulation)
• Allows programmer to define a class (abstract data type)
• One instance (variable) of a class is called an object
• The data and operations of a class are called its members.
A Class & Its Objects
class Rectangle Rectangle r1;
{ Rectangle r2;
Rectangle r3;
private://by default
int width;
int length;
public:
void set(int w, int l);
int area();
};
Define a Class Type
class Rectangle
class class_name {
{ private:
permission_label:
int width;
member;
permission_label: int length;
member; public:
... void set(int w, int l);
};
int area();
};
Another Example
//Circle.cpp file
//Circle.h file // member function definitions
#include <iostream.h> circle::circle(){radius = 0.0;}
void display (double r){
class circle cout << r << endl;
{ }
private:
double radius; void circle:: store(double r){
radius = r;
public: }
circle(); double circle::area(){
void store(double); return 3.14*radius*radius;
double area(); }
void display(); void circle::display(){
}; cout << “r = “ << radius << endl;
void display(double r); }

//main.cpp file
int main(void) {
circle c; // an object of circle class
c.store(5.0); cout << "The area of circle c is " << c.area() << endl;
c.display();
}
Class Definition - Access Control
• Information hiding
• To prevent the internal representation from direct access from outside
the class
• Access Specifiers
• public
• may be accessible from anywhere within a program
• private
• may be accessed only by the member functions, and friends of this
class, not accessible to nonmember functions
• Protected
• Accessible only to derived/child + same class member functions
• Difference between classes and structs in C++
 the default access specifier is private in class
 the default access specifier is public in struct
Class Definition – Member Functions
• Used to
• access the values of the data members (accessor/get method)
• perform operations on the data members (modifier/set method)
• Are declared inside the class body, in the same way as
declaring a function
• Their definition can be placed inside the class body, or
outside the class body
• Can access both public and private members of the class
• Can be called using dot (for an object) or arrow (for a
pointer to an object) member access operator
Define a Member Function
class Rectangle
{
private:
int width, length;
public:
void set (int w, int l){width=w;length=l;}
int area() {return width*length; }
}

Rectangle r1;
r1.set(5,8);

Rectangle *rp=&r1;
rp -> set(8,10);//equivalent to: r1.set(8,10); or (*rp).set(8,10);
Defining Methods Separately
• For methods/functions that are declared but not defined in the class we
need to provide a separate definition
• To define the method, you define it as any other function, except that
the name of the function is written as:-

ClassName::FuncName
:: is the scope resolution operator, it allows us to refer to parts of a class or
structure
Defining Member Functions
class Rectangle
{
private:
int width, length; class name
public:
void set (int w, int l);
member function name
int area() {return width*length; }
}

void Rectangle :: set (int w, int l)


Rectangle r1;
{
r1.set(5,8);
width = w;
Rectangle *rp; length = l; scope operator
rp->set(8,10);
}
Inline Functions
• In an inline function, the C++ compiler does not make a function call, instead the code of
the function is inserted (in .exe file) in place of the function call (and appropriate argument
substitutions are made)
• Why used?
• It saves the memory space when a function is likely to be called many times (no stack
push happens)
• When we need to make the function call very fast.
• E.g. for accessing/changing fields of a class (set/get methods)
• Compiler replaces the definition of inline functions at compile time instead of referring
function definition at runtime.
• Typically done for simple/small functions; because otherwise exe file will become very
large
• Inline functions’ declaration and definition can’t be split into .h and .cpp files
inline int sum(int a, int b)
{ return a+b; }//inline is a keyword that
//tells the compiler that this
//function is inline
Member Functions defined within class
declaration are automatically inline functions

class Rectangle
{
private:
int width, length;
public:
void set (int w, int l);
int area() {return width*length; }
}

Automatically inline function;


no need to use inline keyword
before function header
Three Types of Functions
• Class member functions are classified into three categories:
• Constructors
• create objects (allocate memory, set initial state)
• Modifiers/set-methods
• change the state of objects
• Accessors/get-methods
• make information about the state of the object available outside the class
Constructor
• Goal:
• construct objects of the class
• allocate memory
• Constructors MUST have the same name as the class itself.
• They don't have a return type. It's simply omitted.
• Constructors can be overloaded, i.e., a class can have several constructors that have the same name but
different lists of parameters
• That's how you'll make instances of the class (objects).
• Example:
• Constructor of dateType class
• dateType();
• Constructor of rectangle class
• rectangle();
Constructor (Cont.)
• A default constructor: no parameters
• Initializer constructors: parameters specifying initial state of an object

• A copy constructor
• Called when an object is copied to another object of the same type
• Copy constructor is called when we:
• Initialize one object from another of the same type.
• Copy an object to pass it as an argument to a function.
• Copy an object to return it from a function.
• If no copy constructors is declared in the class, then an object is bitwise copied to another
object in the above 3 cases – which may be problematic especially if the objects contain
any pointer. That’s why it’s a good practice to put a copy constructor.
Constructor Example
class Rectangle{
public:
int width, length;
Rectangle(){width=length=0;} //default constructor
Rectangle(int w, int l){width=w; length=l;} //constructor with initializers
//copy constructor
Rectangle(const Rectangle &r){width=r.width; length=r.length;}
};
void print(Rectangle r){cout << r.width << ‘ ‘ << r.length << endl;}
Rectanlgle create(int w, int l){Rectangle r; r.width=w; r.length= l; return r;}

Rectangle r1; //default constructor is called


Rectangle r2(5,3.4); //initializer constructor is called
Rectangle r3= r2; //copy constructor is called: r3.Rectangle(r2);
print(r3); //copy constructor is called: Rectangle r = r3;//r.Rectangle(r3);
Rectangle t= create(4,2); //copy constructor is called: Rectangle t = r;
Destructor Function
• A destructor is a special member function that is called when the lifetime of an
object ends.
• The purpose of the destructor is to free the resources that the object may have
acquired during its lifetime.
• In a C++ class, destructor should be provided when memory is dynamically
allocated for some members of that class, because C++ doesn’t have an
automatic garbage collection mechanism (unlike Java)
• Destructor syntax:
~ class_name ();
Destructor Example
#include <iostream>
using namespace std;
ctor a1
ctor a2
struct A{
int *i; dtor a2
A (int k) {
i = new int; dtor a1
*i = k; Destructor Example Output
cout << “ctor ” << *i << '\n';
}
~A() {cout << “dtor ” << *i << '\n'; delete i;} //destructor
};

int main(){
A a1(1);//constructor is called to instantiate a1
if(1){ // nested scope
A a2(2); //constructor is called to instantiate a2
} // a2 out of scope; so destructor is called on a2
} // a1 out of scope; so destructor is called on a1
Class in a Separate Header File for Reusability
• For every data structure, we will create 3 files in
our Codeblocks project
• The declaration file (with .h extension)
• The definition file (with .cpp extension) • Header files
• The driver file (with .cpp extension) • Separate files in which class definitions are placed.
• Allow compiler to recognize the classes when used
elsewhere.
• Generally have .h filename extensions

• .cpp files for source-code implementations


• Class implementations
• Main programs
• Test programs

• Driver file
• A program used to test software (such as classes).
• Contains a main function so it can be executed
Basics
#ifndef DYNARR_H_INCLUDED
#define DYNARR_H_INCLUDED

class dynArr
{
private:
int *data;
int size;

public:
dynArr();
dynArr(int);
~dynArr();
void allocate(int);
void setValue(int, int);
int getValue(int);
};

#endif // DYNARR_H_INCLUDED

dynarr.h (header file)


Basics
#include "dynarr.h" void dynArr::allocate(int s)
#include <iostream> {
using namespace std; if(data!=NULL) delete [] data;
data = new int[s];
dynArr::dynArr() size = s;
{ }
data = NULL;
size = 0; int dynArr::getValue(int index)
} {
return data[index];
dynArr::dynArr(int s) }
{
data = new int[s]; void dynArr::setValue(int index, int
size = s; value)
} {
data[index] = value;
dynArr::~dynArr() }
{
if(data!=NULL)
delete [] data;
} dynarr.cpp (definition file)
Basics
#include "dynarr.h"
#include <iostream>
using namespace std;

int main()
{
int n;
cin>>n;
dynArr d(n);
int i;

for(i=0;i<n;i++)
d. setValue(i,3*i+1);
for(i=0;i<n;i++)
cout << d.getValue(i) << endl;
d.allocate(100);//reallocate space
for(i=0;i<n;i++)
cout << d.getValue(i) << endl; //prints garbage values
return 0;
}
main.cpp (driver file)
Template Class
• Now we have a neat class that gives us a 1D dynamic array (you are free to make
your own improvisations at home by adding more functions to the class)
• But it only works for integer type
• What if we are to make it versatile, so that it works for any type, e.g. float,
double and char
• Should we have separate classes for each type?
• Write the same code for each type with just minor changes?
• Instead, we can use template classes
Template Class
#ifndef DYNARR_H_INCLUDED
#define DYNARR_H_INCLUDED

template <class T>


class dynArr
{
private:
T *data;
int size;

public:
dynArr();
dynArr(int);
~dynArr();
void allocate(int);
void setValue(int, T);
T getValue(int);
};

#endif // DYNARR_H_INCLUDED
dynarr.h (declaration file)
Template Class
#include "dynarr.h" template <class T>
#include <iostream> void dynArr<T>::allocate(int s)
using namespace std; {
if(data!=NULL) delete [] data;
template <class T> data = new T[s];
dynArr<T>::dynArr() size = s;
{
}
data = NULL;
size = 0;
} template <class T>
T dynArr<T>::getValue(int index)
template <class T> {
dynArr<T>::dynArr(int s) return data[index];
{ }
data = new T[s];
size = s;
template <class T>
}
void dynArr<T>::setValue(int index, T
template <class T> value)
dynArr<T>::~dynArr() {
{ data[index] = value;
delete [] data; }
} dynarr.cpp (definition file)
Template Class
#include "dynarr.cpp"
#include <iostream>
using namespace std;

int main()
{
dynArr<int> di(10);
dynArr<double> dd(10);
int i;

for(i=0;i<10;i++)
{
di.setValue(i,3*i+1);
dd.setValue(i,7.29*i/1.45);
}
for(i=0;i<10;i++)
cout << di.getValue(i) << " " << dd.getValue(i) << endl;

return 0;
}
main.cpp (driver file)
A Complex Number Example
class Complex
{ Complex Complex::Add(Complex c)
public: {
Complex(); Complex t;
Complex(double, double); t.Real = Real + c.Real;
Complex Add(Complex); t.Imaginary = Imaginary + c.Imaginary;
void Print(); return t;
private: }
double Real, Imaginary; void Complex::Print()
}; {
cout << Real << endl;
Complex::Complex() cout << Imaginary << endl;
{ }
Real = 0;
Imaginary = 0;
} int main(void)
{
Complex::Complex(double r, double i) Complex A(1,1), B(2,3);
{ Complex C;
Real = r; C = A.Add(B);
Imaginary = i; C.Print();
} return 0;
}
Optional Part
Namespace (https://www.youtube.com/watch?v=ZZWTh142s4w)
#include <iostream> #include <iostream>
using namespace std; using namespace std;
namespace First { namespace First{
void sayHello() { void sayHello(){
cout << "First Namespace“ << endl; cout << "First Namespace" << endl;
} }
} }
namespace Second { namespace Second{
void sayHello() { void sayHello(){
cout << "Second Namespace“ << endl; cout << "Second Namespace" << endl;
} }
} }

int main() using namespace First;


{
First::sayHello(); int main () {
Second::sayHello(); sayHello();
return 0; return 0;
} }
Friend Function
class Complex
{
public:
Complex();
Complex(double, double);
void Print();
friend Complex AddComplex(Complex, Complex);
private:
double Real, Imaginary;
};

Complex::Complex() • The function has access to the private


{ members in the class declaration
Real = 0;
Imaginary = 0;
• The function is outside the scope of the class
}

Complex::Complex(double r, double i)
{
Real = r;
Imaginary = i;
}
Friend Function
void Complex::Print()
{
cout << Real << endl;
cout << Imaginary << endl;
}

Complex AddComplex(Complex a, Complex b)


{
Complex t;
t.Real = a.Real + b.Real;
t.Imaginary = a.Imaginary + b.Imaginary;
return t;
}

int main(void)
{
Complex A(1,1), B(2,3);
Complex C;
C = AddComplex(A, B);
C.Print();
return 0;
}
Operator Overloading
class Complex {
public:
Complex();
• We can use some operator symbols to
Complex(double, double); define special member functions of a class
Complex operator+(Complex);
Complex operator+(double); • Provides convenient notations for object
void Print(); behaviors
private:
double Real, Imaginary;
};
Complex::Complex()
{
Real = 0;
Imaginary = 0;
}
Complex::Complex(double r, double i)
{
Real = r;
Imaginary = i;
}
Operator Overloading
Complex Complex::operator+(Complex a){
Complex t;
t.Real = Real + a.Real;
t.Imaginary = Imaginary + a.Imaginary;
return t;
}
Complex Complex::operator+(double n){
Complex t;
t.Real = Real + n;
t.Imaginary = Imaginary + n;
return t;
}
void Complex::Print(){
cout << Real << endl;
cout << Imaginary << endl;
}
int main(void) {
Complex A(1,1), B(2,3), D(5,6), C;
C = A + B; //C = A.operator+(B);
C = C + 3.2; //C = C.operator+(3.2);
C.Print();
return 0;
}
Operator Overloading using friend function
 With simple operator overloading we can’t do:
Complex A, C = 3.2+A;

 To be able to write expressions like above, we need friend operator


function
Operator Overloading with friend function
class Complex {
double Real, Imaginary; //private, by default
public:
Complex();
Complex(double, double);
friend Complex operator+(double, Complex);
friend Complex operator+(Complex, double);
// Complex operator+(double n)
friend Complex operator++(Complex&);
void Print();
};
Complex::Complex()
{
Real = 0;
Imaginary = 0;
}
Complex::Complex(double r, double i)
{
Real = r;
Imaginary = i;
}
Operator Overloading with friend function

Complex operator+(double n, Complex a){


Complex t;
t.Real = n + a.Real;
void Complex::Print(){
t.Imaginary = n + a.Imaginary;
cout << Real << endl << Imaginary << endl;
return t;
}
}
int main(void) {
Complex operator+(Complex a, double n){
Complex A(1,1), B;
Complex t;
B = 3.2 + A;//operator+(3.2, A);
t.Real = n + a.Real;
A = A + 2.4;
t.Imaginary = n + a.Imaginary;
B=++A;//operator++(A);//a=A
return t;
A.Print();B.Print();
}
return 0;
Complex operator++(Complex &a) {
}
a.Real ++; a.Imaginary ++;
return a;
}
Overloading Relational Operator
class Complex {
public:
Complex();
Complex(double, double);
bool operator>(Complex);
void Print();
private:
double Real, Imaginary;
};

Complex::Complex() {
Real = 0;
Imaginary = 0;
}

Complex::Complex(double r, double i) {
Real = r;
Imaginary = i;
}
Overloading Relational Operator
bool Complex::operator>(Complex a){
if(Real > a.Real || (Real == a.Real && Imaginary > a.Imaginary))
return true;
else
return false;
}
void Complex::Print(){
cout << Real << endl;cout << Imaginary << endl;
}
int main(void) {
Complex A(1,1), B;
A.Print();
B.Print();
if(A>B) //A.operator>(B);
cout<<“A is greater”;
return 0;
}

You might also like