Cpp Slides

  • November 2019
  • PDF

This document was uploaded by user and they confirmed that they have the permission to share it. If you are author or own the copyright of this book, please report to us by using this DMCA report form. Report DMCA


Overview

Download & View Cpp Slides as PDF for free.

More details

  • Words: 11,900
  • Pages: 231
Programming in C++

Road Map

• Introduction to C++ Programming Language – Introduction to historical program cycle of build

• • • • • •

A sample C++ program C styled C++, similarities and differences Inline functions and macros The variable argument list Namespaces The linkage specification: Using Extern

Road Map … • • • • • • • • • • •

Features of P/OOPS Classes, objects, methods, scopes, and inline nature Constructor and destructor Explicit constructor Copy constructor Default Object assignment and = operator Thumb Rules for class The constant functions and modification: mutable The static data and methods The early overloading: brief on ambiguity Pointers and references

Road Map … • Overloading operators • Communication – Partial (Friend) • Access and communication

– Complete (Inheritance) • • • •

Reusability Virtual Inheritance and ambiguity with base class members Access control (Inheritance and protected members) Granting Access

• Virtual function, VTABLE, and pure virtual functions – – – –

Inherited Virtual attribute, hierarchical The relation among classes and their behavior: A simple VTABLE Abstract classes (pure virtual function) Early binding vs. late binding

Road Map … • Templates – – – – –

Generic function Generic Class templates Generic function and class restriction Explicit function and Explicit class specialization A brief on typename and export keywords

• Exception handling – – – – – – –

Fundamentals The try-catch, throw Multiple and Nested catches Catching class type exception Handling Derived class exceptions Catching all exceptions Terminate, unexpected, uncaught Exception function

Road Map … • C++ File I/O – – – – – –

Fstream and the File classes Opening and closing a file Reading and writing a text file Handling unformatted data Detecting EOF Random access and obtaining current file position

• RTTI – Introduction to typeid – Applying typeid to templates – C++ typecast, Conversion function, Cast operators • Dynamic_cast, constant_cast, Static_cast, reinterpret_cast

Introduction to language

WHAT IS A LANGUAGE? • A language is someone’s response to a set of problems at a given time. • The problems and our understanding of solutions change over time. • A language lives and grows

C lovers

Think Hard

Historical Notes • C++ owes most to C.

C++ 1987

– Other ancestors are Simula67 & Algol68.

• First versions of C++ in 1980 under the name “C with classes”. – Since 1983 the name C++ is used.

• 1990: ANSI/ISO 9899 defines a standard for C • 1998: ISO/IEC 14882 specifies the standard for C++

C++ keywords

asm

dynamic_cast

namespace

reinterpret_cast

bool

explicit

new

static_cast

catch

false

operator

typeid

delete

inline

private

class

friend

public

this

typename

protected

throw

wchar_t

Virtual

true

mutable

try const_cast using template

C++ keywords from C

auto

const

double

float

int

short

struct

unsigned

break

continue

else

for

long

signed

switch

void

case

default

enum

goto

register

sizeof

typedef

volatile

char

do

extern

if

return

static

union

while

Traditional Sample Program: Hello World

#include using namespace std; // c++ styled comments int main() { cout<<“Hello World in C++”<<endl; return 0; }

More codes … int accept() {

char name[11]; int age cout<<“Enter your name and age”; cin>>name>>age; return age;

} int (*fun_handler)(); // a std c call is made as (*fun_handler)(); int main() {

onwards, std C++

accept(); //direct calls fun_handler=accept; fun_handler() ; // it works from ANSI C return 0; }

Data’s Scope int ivar=9; int main() { int ivar=7; { int ivar = 5; cout<<“Global scope ”<< ::ivar<<endl; cout<<“Inner block ”<
No default to int Fun(int ) ; /* Defaults to integer return. Not to be used in standard C++. Though, compilers takes it up as standard C / old C++ style */ int Fun(int); // should use this way double Fun(); char *Fun(); double Fun( uiarg, siarg) // K&R style not allowed as std c++ unsigned uiarg; int siarg; Must use as done previous

Default value to arguments int Fun(int x=4,int y=6) ; //controversial feature (do not use it) Fun(); // 4,6 Fun(10); //10,6 Fun(10,20); // 10 , 20 --------------------------------------Case 1------------------------------------------------------------------------.h file------------------------int Fun(int x=4,int y=6) ; -------------------------file that includes .h---------------int Fun(int x=4,int y=0) ; // illegal, cant redefine --------------------------------------Case 2------------------------------------------------------------------------.h file------------------------int Fun(int x=4,int y) ; -------------------------file that includes .h---------------int Fun(int x=4,int y=0) ; // allowed

Inline functions & macros •Inline is a new storage class used in functions as if it were a macro. •Unlike a macro, an inline function does not have side effects. For Example: #define toupper(c) (islower(c) ? (c) + (‘a’ – ‘A’) : (c)) •When invoked with toupper(*p++) expands to :

#define toupper(*p++) (islower(*p++) ? (*p++) + (‘a’ – ‘A’) (*p++)) and increments p twice.

An inline function does not exhibit this behavior. Looks as: inline toupper(int ivar) {return islower(c) ? c + (‘a’ – ‘A’): c; } // invokes pointer only once

Inline functions & macros … •Moreover as we have toupper as a function, the compiler can do argument checking – impossible with a macro •An inline function also solves the multiple line macro problem. •You can’t do this with macro: inline two_things() { int ret = a() ; b() ; return ret ; } •Remember Inline is just a suggestion. •Compiler might treat the function out of line.

Using namespace #include using std::cout; using std::cin; using std::cerr; using std::endl; int main() {

int ivar; cout<<“using std namespace enter an integer ”<<endl; cin>>ivar; if(false) cerr<<“this message is going to err log.”<<endl; return 0;

}

Using namespace … // another way of representation #include int main() { std::cout<<“Hello world”<<std::endl; std::cin>>ivar; if(false) std::cerr<<“this message is going to err log.”<<std::endl; return 0; }

Using namespace … namespace rtos { int dontknow; class MsgQ { char *message; public: MsgQ(){} MsgQ(char *msg, int size); };

}

Using namespace …

rtos::MsgQ::MsgQ(char *msg,int size) { message = new char[size+1]; message = msg ; cout<<"Message [ "<<message<<" ] copied with [ "<<size<< " ] bytes.\n"; }

Using namespace … int main() { char *str = "Hello World."; int len; for(len=0; str[len]!='\0';len++); rtos::dontknow = len; // this is how I know dontknow = len will not work rtos::MsgQ mobj(str,rtos::dontknow); using namespace rtos; // Mark this well dontknow = 24; MsgQ newobj("Bye Bye! cruel world :(",dontknow); return 0; }

Nested namespace … A namespace should be globally declared exception to hide you namespace(s) Example: namespace RTOS {

static int smp_w_lock;

namespace GPOS { a task}

static int named_pipes; // no of pipes used by }

Accessing named_pipes is: RTOS::GPOS::named_pipes = 2 ; // default read/write channel to every process Or using namespace RTOS; will allow GPOS::named_pipes = 2;

Multiple declaration namespace … •There may be more than one Namespace declaration of the same name. •This allows it to be split over several files or even within the same file. •For Example: namespace RTOS {

static int smp_w_lock; ……………}

namespace RTOS {

static int no_of_current_task; ……………}

•This can be easily allowed and provide use of splitting heavy declarations; •Accessing is as same way int main(){ RTOS:: smp_lock == 5; // 5 processor now is using a w_lock RTOS:: int no_of_current_task = 1; //ideal task is default running} return 0;} •A namespace must be globally declared (outside all the scope) exception is nested namespaces as discussed earlier.

The linkage specification: Using Extern •The extern keyword is extended from c, the only powerful keyword •Allows the data, methods the files of same/different languages to communicate •It provides the true meaning of declaration too! •No storage is done for data,methods of type extern. •It needs to be redeclare/define somewhere else. •This linker is supposed to know before it could create an executable image. •Compiler simply ignore the extern statements

Using extern variable //File: extern-scope.cpp int *stack_signature = 0x1234;

Ready to Run

linker

//File memory-barrier.cpp void* fix_stack_signature() { extern int *stack_signature; static int count; while(count++ <= MAX_SIZE) { stack_signature++; // rest of the code goes here //…. return (void*)link; } main() { Task *task1=(task*)fix_stack_signature(); }

Using extern for Mixed language •extern “C” void cfree(int*, char*) ; •Describes compiler that this function is expanded under c and linkage specification is to be made from it • We can declare group of function together for the same

•extern “C” {

void cfree(int*, char*); int lock(Task *task); ………

} •A statement like following is too! Legal and very useful

•extern “C” { #include “c_extern_decl.h” #include “f77_extern_decl.h” }

P/OOPS Programming Concept Classes, object, constructors, Inheritance, Polymorphism, Encapsulation, and Abstraction, …

P/OOP Concepts under C++

Inheritance Polymorphism Objects Objects

E n c a p s u l at i o n Abstraction

classes

Classes and objects

Classes and objects Classes form the basis of object oriented programming The class is used to express the nature of an object that would result in existence Thus, class is a logical abstraction Why OOP not COP? Well it’s the object that exists but what’s that Everything is an object! Says Bruce Eckel! Objects are real and they consume space

Classes and objects … A class is a logical method to organize data and functions in the same structure. They are declared using keyword class, whose functionality is similar to that of the C keyword struct, but with the possibility of including functions as members, instead of only data. Its form is: class class_name { permission_label_1: member1; permission_label_2: member2; ... } object_name; where class_name is a name for the class (user defined type) and the optional field object_name is one, or several, valid object identifiers. The body of the declaration can contain members, that can be either data or function declarations, and optionally permission labels, that can be any of these three keywords: private:, public: or protected:.

Classes and objects … Class make reference to the permission which the following members acquire: •private members of a class are accessible only from other members of their same class or from their "friend" classes. •protected members are accessible from members of their same class and friend classes, and also from members of their derived classes. •Finally, public members are accessible from anywhere the class is visible. If we declare members of a class before including any permission label, the members are considered private, since it is the default permission that the members of a class declared with the class keyword acquire.

Classes and objects … For example: class CRectangle { int x, y; public: void set_values (int,int); int area (void); } rect; Declares class CRectangle and an object called rect of this class (type). This class contains four members: Two variables of type int (x and y) in the private section (because private is the default permission) and two functions in the public section: set_values() and area(), of which we have only included the prototype.

Classes and objects … On successive instructions in the body of the program we can refer to any of the public members of the object rect as if they were normal functions or variables, just by putting the object's name followed by a point and then the class member (like we did with C structs). For example: rect.set_value(3,4); myarea = rect.area(); but we will not be able to refer to x or y since they are private members of the class and they could only be referred from other members of that same class. Let’s see a complete example of class CRectangle:

Classes and objects … #include using namespace std; class CRectangle { int x, y;

int main () {

public:

CRectangle rect;

void set_values (int,int);

rect.set_values (3,4);

int area (void) {return (x*y);} }; void CRectangle::set_values (int a, int b) { x = a; y = b; }

cout << "area: " << rect.area(); }

structures and classes are related Structures are used same as classes but their access right are public by default and private in class as default. Struct can be used as classes: Struct Human{private: int age; public: char *nick_name; protected: set_age(); }ram;

Now Human in a struct truly as a class.

unions and classes are related Like structure, a union may also be used to define as class. Union may contain methods and data members. It may also contain constructor and destructors. Like structures, union are also placed as public by default. Anonymous Union int main(){ union{ double dROI; int iref_code; char scmsg;}; dROI=000009.8125; // access as a variable return 0; }

Restrictions in Union

•A union cannot inherit any other classes of any type •A union cannot be a Base class •It cannot have virtual member functions •Unions cannot have static data members •Try above statements within your lab

Encapsulation The least understood of the three concepts is encapsulation. Sometimes, encapsulation is also called protection or information hiding. In fact, encapsulation, protection and information hiding are three overlapping concepts Encapsulation is the inclusion within a program object of all the resources need for the object to function - basically, the method and the data. Other objects adhere to these interfaces to use the object without having to be concerned with how the object accomplishes it.

Encapsulation … An object can be thought of as a self-contained atom. The object interface consists of public methods and instantiate data. Protection and information hiding are techniques used to accomplish encapsulation of an object. Protection is when you limit the use of class data or methods. Information hiding is when you remove data, methods or code from a class's public interface in order to refine the scope of an object. So, how are these three concepts implemented in C++? You'll remember that C++ classes have a public, protected and private interface. Moving methods or data from public to protected or to private, you are hiding the information from the public or protected interface.

Encapsulation … If you have a class A with one public integer data member d, then the C++ definition would be... class Home { public: integer doors; }; If you moved that data member from the public scope of the private scope, then you would be hiding the member. Better said, you are hiding the member from the public interface. class Home { private: integer doors; };

Constructors and destructors, const members, copy constructors and default assignment

Constructors and destructors

Constructor: •Constructors build objects from dust. •Constructors are like "init functions". They turn a pile of arbitrary bits into a living object. •Minimally they initialize internally used fields. They may also allocate resources (memory, files, semaphores, sockets, etc). •"ctor" is a typical abbreviation for constructor.

Constructors and destructors … •Destructors •A destructor gives an object its last rites. •Destructors are used to release any resources allocated by the object. •E.g., class Lock might lock a semaphore, and the destructor will release that semaphore. The most common example is when the constructor uses new, and the destructor uses delete. •Destructors are a "prepare to die" member function. They are often abbreviated "dtor".

Constructors and destructors … class CRectangle { int *width, *height; public: CRectangle (int,int); ~CRectangle (); int area (void) {return (*width * *height);} }; CRectangle::CRectangle (int a, int b) { width = new int; height = new int; *width = a; *height = b;

}

CRectangle::~CRectangle () { delete width; delete height;} int main () { CRectangle rect (3,4), rectb (5,6); cout << "rect area: " << rect.area() << endl; cout << "rectb area: " << rectb.area() << endl; return 0;}

When are constructor and destructor executed? •Important to note that they are implicit calls •Compiler always includes one[Even if you do not] •Constructors are called as the object is created •Destructors are executed as reverse order of object creation •Class CtorDtor{ pubilic: CtorDtor(int ival) { cout<
The Explicit keyword: avoiding default assignment class Exp {

int intCount; public: explicit Exp(int intTemp)

{

intCount = intTemp ; cout<
The default = operator class Exp {

int intCount; public:Exp(){}; Exp(int intTemp)

{

intCount = intTemp ; cout<
The thumb rule for Class

A class should have a minimum two thumb rules

•A copy constructor •An overloaded = operator •We will look this further with operator overloads

The constant functions and modification: mutable class Demo {

//mutable int intVar; Allows const members to modify int intVar; public: int getVar() const { return intVar*intVar;} int setVar(int intLocal) const {intVar = intLocal;} // error try modifying

}; int main() { Demo demoObj; demoObj.setVar(10); cout<<"The value set is ="<<demoObj.getVar()<<endl; return 0; }

Sharing Data: static data, and methods

The static data and methods: shared data Static data members and functions: •When you are using a static variable you are saying compiler that you will be using only one copy of it. •In turn you are trying to use a shared resource •Unlike other data members individual copies of static are not made for each object. •The data is assigned to 0 by default •Declaration of static done within a class means a linkage specification is needed ie; should be assigned with scope of class it is assigned to. •A static member exists before any object of its class is created. •One of the typical Application of static is access control

The static data and methods: shared data Static data members and functions:

•Methods too! Can be static

•There are several restrictions to this •They may only directly refer to the other static members of class •Global data and functions may be accessed by static methods •No this pointer is associated with it •It cannot be virtual •Finally, they cant be const and volatile

An example: static data Class Shared {

public: static int shared; };

int Shared :: shared; // defaults to 0 int main(){ Shared::shared = 100; // accessing Shared shared_obj; shared_obj.shared ; // All class objects can use it too! }

An example: resource allocation detail Class SharedResource{

static int Resource; public: int getResource(); void freeResource(){Resource=0;}}; int SharedResource :: Resource; void SharedResource::getResource(){ if(Resource) return 0; else{ Resource=1; return 1; } int main(){ SharedResource task1, task2; if(task1.getResource()) cout<<“task1 has resource”<<endl; if(!task2.getResource()) cout<<“Resource busy”<<endl; task1.freeResource(); if(task2.getResource()) cout<<“task1 has resource”<<endl; task2. freeResource(); } // try a code to maintain the number of tasks currently being used

An example: static methods class Sinit{ static int ival; public: static int f(int &temp) { ival=temp; cout<<<endl;} }; int Sinit::ival; int main(void) { int ilocal=10; Sinit::f(ilocal); return 0; }

Static/Early Overloading and ambiguities

Aspects of Overloading •We have also observe that the default parameters can be very confusing. But applications sometime needs that or sometimes we can use it as a short hand for overloading •Overloading is an alternative and respected answer default parameters that provides the flexibility and convenience •It also is towards the definition aspect for language as explains much about the static aspects of polymorphism •The secret of overloading is that each redefinition of the methods must use either different type of parameters or the no. of parameters •Overloads also leads to ambiguity at times.

Ambiguities under Overloading

•Example of a function overloaded •int abs(float f) {return iabs>0?iabs:-iabs; }; •int abs(double d) {return iabs>0?iabs:-iabs; };

int main(){ abs(-100); // Ambiguous abs(-100.05); // Unambiguous }

Ambiguities under Overloading …

•Example of another function overloaded •int f( char schar){ return schar;} •int f( unsigned char uchar){ return uchar;}

int main(){ f(97); // Ambiguous f(‘A’); // Unambiguous }

Ambiguities under Overloading …

•Another way a function overloaded can cause ambiguity •int f( int ivar){ return ivar;} •int f( int ivar1, int ivar2=10){ return uchar;}

int main() { f(9); // Ambiguous f(2,4); // Unambiguous }

Ambiguities under Overloading …

•Another way a function overloaded can cause ambiguity •int f( int &ivar){ return ivar;} •int f( int ivar){ return ivar;} // error

int main() { int ivarl=100; f(ivarl); // Ambiguous }

Pointer, References and Dynamic memory allocation

Pointer and References Strict definition •Pointers are cells (often present as two or four bytes) capable of referencing and dereference the memory allocations •References are alias to the variable, offers high performance code play and regarded as true concept of C++ •Pointers can be used as indirect references •Example: •data_type *pointer ; // declaring a pointer •data_type &reference = any_variable; // note the = is a must

Pointer and References

What is the difference between pointer and reference?(strong)

•Pointer can allocate memory at the run time. •Reference cannot! •They are just alias that are used to avoid formation temporary data/objects copy

Pointer to objects

Class Ptr2O{ int ivar; public: Ptr20(int temp) {ivar = temp;ip_var=temp;} int get_val() {return ivar;} int ip_var; }; int main() { Ptr20 obj(10) , *ptr; ptr= &obj ; cout< get_val()<<endl; // calls method ptr=&obj.ip_var ; // only if public variable cout<<*ptr<<endl; }

Type checking C++ Pointers

int main() { int *i_ptr; float *f_ptr; i_ptr = f_ptr ; // type mismatch } •C++ stronger type checking where pointers are involved, are different from C, in which you may assign any value to any pointer.

•Though by casting it to the type is allowed but doing so is just by-passing c++’s type check mechanism.

this pointer •When a method is called, it is passed (a this pointer) as an implicit argument that is a pointer to the invoking object. I.e.the object on which a method is called. •Theses type of pointer is called as [this pointer] represented as *this. Example:

class This{ int ivar; public: This (int itemp) { ivar = itemp;}};

Within a method ivar needs no object for access: here ivar = itemp; means a copy of ivar associated with the invoking object will be assigned the value containing itemp. The statement can be rewritten as this->ivar = itemp; where this pointer refers to that object’s ivar; Nothing is gained by applying it explicitly and hence use of this under such situation is useless. However this plays a very important role under operator overloading as we will see later.

References



As we know what reference is, the need to know is the three ways a reference can be used

1.

As a function parameter

2.

As a function returning references

3.

Independent references

Reference Parameters void negate(int *itemp){

void negate(int &itemp){

*itemp = -itemp ; }// manually

itemp = -itemp ; }

int main() { int ilvar=1; neg(&ilvar); // manual call via pointers neg((ilvar); // no & requires } Note: Remember when you assign a value to reference, you are actually assigning value to that variable what reference pointer points to.

Passing Reference to objects Class Ref{ int id; public: int ivar; Ref (int temp){ cout<<“Constructing ”<
Returning References char str[]=“Hello World” ; char &replace(int iposition) { return str[iposition] ; } int main(){ replace(5) = ‘Y’; cout<<str<<endl; return 0; } •

Returning references allows function to be used on the left hand side as shown above. A significant left function assignment

Independent References •

You can declare a reference that is simply a variable.



This type of reference is called independent references. Example: int ival=10; int &ref = ival; ref = 11; int b = 20; ref = b ; ref --; decrement b not ref

Restrictions to References •

You cannot reference another reference or say you cannot obtain address of references



You cannot create arrays of references



You cannot create a pointer to a reference



You cannot a reference bit



A reference must be initialized when it is declared unless it is a member of a class, function parameter, or a return value



Null references are prohibited

C++ Dynamic Memory Allocation •

C++ provides dynamic memory allocation operators: •



new and delete

The general forms of new and delete is as follows: p_var = new type ; delete p_var; // •

P_var is a pointer variable that receives a pointer to memory that is large enough to hold an item of the type



If new fails, an exception bad_alloc is thrown



This exception is defined in



If exception handling is not handled program terminates



New has been implemented differently over the time

C++ Dynamic Memory Allocation •

Initializing allocated memory: •





P_var = new var_type(initilizer);

Allocating Arrays •

P_var = new array_type[size]



delete [] p_var

Allocating objects •

p_var = new



Delete p_var;

C++ Dynamic Memory Allocation • The nothrow Alternative: In std C++, it is possible to have new return null instead of throwing an exception while allocation fails. • This is valuable when you are replacing old c codes of malloc() with new. • P_var = new (nothrow) type ;

Friends

Partial Communications:friend keyword



Friend keyword add flexibility to the communication between two different object. [typical example in overloading(coming up next)]



It is possible to grant a non member function to the private members of a class by using a friend



Friend can be applied to





Non member Methods



Class

It is you to decide the privacy rules as to allow a good friend!or not?

Friend function class taskY; //Forward declaration class taskX{

int current_stack_size; public: taskX(int itemp){ current_stack_size = itemp;} friend int total_stack_usage(task X, task Y)

}; class taskY{

int current_stack_size; public: taskY(int itemp){ current_stack_size = itemp;} friend int total_stack_usage(taskX , task Y)

}; int total_stack_usage(taskX xobj, taskY yobj) { return xobj.current_stack_size + yobj.current_stack_size ; }

Friend function int get_resource_size( ) { return 120;} int main() { taskX taskx (get_resource_size()); taskY tasky (get_resource_size()); cout<< “ The total memory consumed by various tasks is: “; cout<< total_stack_usage(taskx, tasky) <<endl; }

Friend as classes: weak privacy class pipes; class Bucket{

char block_buffer[1501]; /1 eth packet payload public: Bucket(){ block_buffer=‘\0’;}; void get_payload(char *buf) { strcpy(block_buffer,buf);} friend class pipes;

}; class pipes{ char p_buf[2]; public: void read_char(Bucket); }; void pipes:: read_char(Bucket bobj){ int i=0; while( bobj.block_buffer[i] != ‘\0’){ p_buf[0]= bobj.block_buffer[i] ; p_buf[1]=‘\0’;

Friend as classes: weak privacy

cout<
Overloading operators

Overloading basics •

Class is an special user defined data type supporting OOP, no operators except = is provided for objects. To gain we need to overload them.



Almost all operators can be overloaded



:: ?: . and .* are restricted for overloads



This is useful for performing special job your class can operate



Creating a member operator function ret_type class_name::operator O(arg_list) { // operations }

where

O is the place holder ret_type is generally an object but can be any other too! if you need? arg_list is empty if operator is unary, one if binary

Overloading operation: An complete Example # include < iostream> using namespace std ;

class loc { int longitude, latitude ;

public : loc () { } // needed to construct temporaries loc (int lg, int lt) { longitude = lg ; latitude = lt ; }

Overloading operation: An complete Example

void show () { cout << longitude << “ “ ; cout << latitude << “\n” ; }

loc operator + (loc op2) ; loc operator – (loc op2) ; loc operator = (loc op2) ; loc opertor ++ () ; };

Overloading operation: An complete Example // Overload + for loc. loc loc : : operator + (loc op2) { loc temp ; temp. longitude = op2.longitude + longitude ; temp. latitude = op2.latitude + latitude ; return temp; } Note: •

+ has one parameter as the operand on left side of the + is passed implicitly to the function through *this pointer. The operand on the right is passed in the parameter op2.



The fact that the left operand is passed using *this implies one point: ie;



When binary operators are overloaded, it’s the object on the left side that generates the calls to the operator function

Overloading operation: An complete Example // overload - for loc. loc loc : : operator – (loc op2) { loc temp ; // notice order of operands temp. longitude = longitude – op2. longitude ; temp. latitude = latitude – op2 . latitude ; return temp ; }

in order to keep the meaning of subtraction, the operand on the right side of the – is subtracted from left because it’s the object on the left that generates the call to the operator-() function. Op2’s data must be subtracted from the data pointed by *this.



Remember always which operand generate calls to the function

Overloading operation: An complete Example // over load assignment for loc. Loc loc : : operator = (loc op2 ) { longitude = op2.longitude ; latitude = op2. latitude ;

return *this; // i.e., return object that generated call } •

If c++ if = default overloaded. This is simply a member-by-member bitwise copy.



By overloading = you can alter the mechanism of it according to the requirement that is generally not needed.



The above is exactly what default does.

Overloading operation: An complete Example

// overload prefix ++ for loc. Loc loc :: operator ++ () { longitude ++ ; latitude ++ ; return *this ; } •

Here, it takes no parameter.

Overloading operation: An complete Example int main () { loc ob1 (10, 20 ), ob 2 (5 , 30), ob 3 (90, 90) ; ob1.show () ; ob2.show () ; ++ ob1; ob1.show () ; // displays 11 21 ob2 + ++ ob1 ; ob1. show () ; // displays 12 22 ob2.show (0 ; // displays 12 22 ob1 = ob2 = ob3 ; // multiple assignment ob1.show () ; // displays 90 90 ob2.show () ; // displays 90 90 return 0 ; } // Avoid that would change the meaning of operator you loaded

Overloading operator using friend(flexibility) class loc

{

int longitude, latitude ; public : loc () { } loc (int lg, int lt ) { longitude = lg ; latitude = lt ; } void show () { cout << longitude << “ “ ; cout << latitude << “\n” ; } friend loc operator + (loc op1, int op2) ; friend loc operator + (int op1, loc op2) ; };

Overloading operator using friend(flexibility)

// + is overloaded for loc + int. loc operator + (loc op1, int op2 ) { loc temp ;

temp.longitude = op1. longitude + op2 ; temp.latitude = op1. latitude + op2 ;

return temp ; }

Overloading operator using friend(flexibility)

// + is overloaded for int + loc. Loc operator + (int op1, loc op2 ) { loc temp ;

temp. longitude = op1 + op2.longitude ; temp. latitude = op1 + op2.latitude ;

return temp; }

Overloading operator using friend(flexibility) int main () { loc ob1 (10, 20), ob2 (5, 30), ob3 ( 7 , 14) ;

ob1.show () ; b2.show () ; ob3.show () ; ob1 = ob2 + 10 ; // both of these ob3 = 10 + ob2 ; // are valid ob1. show () ; ob3.show () ; return 0 ; }

Overloading new and delete

class loc { int longitude, latitude ; public : …. Other as previous void *operator new (size_t size ) ; void operator delete (void *p) ; };

Overloading new and delete

// new overloaded relative to loc. void *loc : : operator new (size_t size) { void *p ; cout << “In overloaded new. \ n” ; p = malloc (size) ; return p ; }

Overloading new and delete // delete overloaded relative to loc. void loc : : operator delete (void * p) { cout << “In overloaded delete . \n” ; free ( p ) ; } int main () { loc *p1, *p2 ; p1 = new loc (10, 20) ; p2 = new loc (-10, -20) ; return 1 ; }

Overloading Special operators [] class atype {int a [3] ;

public : atype (int i, int j, int k )

{

a[ 0 ] = i ; a[1]=j; a[2] =k; }

int operator [ ] (int i) { return a [ i ] ; } }; int main () { atype ob (1, 2, 3) ; cout << ob [ 1 ] ; // displays 2 return 0 ; }

Overloading Special operators () class loc { int longitude, latitude ; public : loc (int lg, int lt)

{

longitude = lg ; latitude = lt ; } void show ()

{

cout << longitude << “ “ ; cout << latitude << “ \ n “ ; } loc operator + (loc op2) ; loc operator () (int i, int j, ) };

Overloading Special operators () // Overload ( ) for loc. loc loc : : operator () (int i, int j) { longitude = I ; latitude = j ; return * this ; } // Overload + for loc. loc loc : : operator + (loc op2){ /*implement as earlier*/} l

Overloading Special operators () int main () { loc ob1 (10, 20) , ob2 (1, 1) ;

ob1.show (); ob1 (7, 8) ; // can be executed by itself ob1. show () ;

ob1 = ob2 + ob1 (10, 10) ; // can be used in expressions ob1.show () ;

return 0 ; }

Case of copy constructor/assignment class eq { //int x; public: int x; eq(){} eq(int temp) { x=temp; cout<<"cons"<<x<<endl; }

Case of copy constructor/assignment … eq( const eq &e) { x =e.x; cout<<"copycon"<<x<<endl; } eq &operator =(const eq &e) { x= e.x; cout<<"= overload"<<x<<endl; return *this; } ~eq(){cout<<"des - called"<<endl;} };

Case of copy constructor/assignment … void f(eq &p) {

cout<<"x= "<
int main() { eq o(10); eq o1 = o; // invoke a copy constructor eq o2 = o1; // invoke copy constructor eq o3; o3 = o2 = o1; // invoke = operator f(o1); f(o2); f(o3); return 0; }

Complex declaration? [pointer to class members] •Class Semaphore{ public: int lock; Semaphore(int temp){ lock = temp;} bool status_busy(){ lock>0?true:false;} }; •Declaration of data member pointer •int Semaphore::*lock_ptr; •lock_ptr=&Semaphore:: lock; //get offset of data member •Declaration of method member pointer •bool (Semaphore::*status_ptr)(); •Status_ptr=&Semaphore::status_busy; //offset of method •Calling is done as •Semaphore Obj(1); •If ((Obj.*status_ptr)()) cout<<“busy”<<endl; //method called •Obj.*lock_ptr; // Is busy >0

[pointer to class members via pointer to object][ use ->*] •Declaration of data/method member pointer •int Semaphore::*lock_ptr; •bool (Semaphore::*status_ptr)(); •Assignment •lock_ptr=&Semaphore:: lock; //get offset of data member •Status_ptr=&Semaphore::status_busy; //offset of method •Calling is done as •Semaphore Obj(1), *ptr; •ptr= &Obj; •ptr->*lock_ptr; •(ptr->*status)();

Inheritance, Accessibility, virtual inheritance, virtual functions, about vtable, and Abstract classes

Inheritance Inheritance is the concept that when a class of object is defined, any subclass that is defined can inherit the definitions of one or more general classes. This means for the programmer that an object in a subclass need not carry its own definition of data and methods that are generic to the class (or classes) of which it is a part. This not only speeds up program development; it also ensures an inherent validity to the defined subclass object (what works and is consistent about the class will also work for the subclass).

Inheritance The simple example in C++ is having a class that inherits a data member from its parent class. class A { public: int d; }; class B : public A { public: }; The class B in the example does not have any direct data member does it? It inherits the data member d from class A. When one class inherits from another, it acquires all of its methods and data. We can then instantiate an object of class B and call into that data member. void func() { B b; b.d = 10; }

Inheritance Class base{ public:

int i,j; void set(int a, int b) {i=a; j=b;} void show(){ cout<<“i = ”<<<“ and j = ”<<j<<endl;}

}; Class derived:public base {}; // 1. Class derived:private base {}; int main(){ derived dobj; dobj.set(12,15) ; dobj.show() ; } /* if 1. Is uncommented following will not compile int main(){ derived dobj; dobj.set(12,15) ; //error dobj.show() ; //error } */

Inheritance and protected member Class base{ protected: int i,j; //private to base public: void set(int a, int b) {i=a; j=b;} void show(){ cout<<“i = ”<<<“ and j = ”<<j<<endl;} }; Class derived: public base { int k; public: void setk(){ k= i * j ; // derive can access i,j } void showk(){ cout<<“k in derived = ”<
Inheritance chain(level) Class base{ protected: int i,j; //private to base public: void set(int a, int b) {i=a; j=b;} void show(){ cout<<“i = ”<<<“ and j = ”<<j<<endl;} }; Class derived1: public base { int k; public: void setk(){ k= i * j ; // derive } void showk(){ cout<<“k ”<
can access i,j in derived1 =

can access i,j in derived2 =

This will not compile … Class base{ protected: int i,j; //private to base public: void set(int a, int b) {i=a; j=b;} void show(){ cout<<“i = ”<<<“ and j = ”<<j<<endl;}

};

Class derived1: private base { int k; public: void setk(){ k= i * j ; // derive can access i,j } void showk(){ cout<<“k in derived = ”<
Protected base class inheritance Class base{ protected: int i,j; //private to base public: void set(int a, int b) {i=a; j=b;} void show(){ cout<<“i = ”<<<“ and j = ”<<j<<endl;} }; // all public n protected member of base becomes protected members of derived Class derived1: protected base { int k; public: void setk() { set(10,20); // may access i, j as eariler k= i * j ; // derive can access i,j } void showk(){ cout<<“k in derived = ”<
Granting Access Class base{ protected: int i,j; //private to base public: int public_var; // is public now void set(int a, int b) {i=a; j=b;} void show(){ cout<<“i = ”<<<“ and j = ”<<j<<endl;} }; // making public variable private Class derived1: private base { public: base:: public_var; //make public again base::i; // not allowed }; Note: Std c++ now has deprecated it. In future it may be replaced with using as per documentation goes

Rough

Virtual base classes: virtual inheritance A iData

iData

B

iData

? Compiler

D

C

Virtual base classes: virtual inheritance The problem with the compiler is ambiguity Allows multiple copies of member? Problem: 1. What if we share it? [best solution] 2. What if we can manual access it [ :: needed] 1.

Solution Is , inherit base class with a key word virtual

2.

Dobj.C::iData = 12 ; (Dobj is D’s object) Or Dobj.B::iData = 12 ; (Dobj is D’s object) The second is a manual way but what if only one copy is required? goto 1.

Polymorphism Inheritance is a very easy concept to understand. Polymorphism on the other hand is much harder. Polymorphism is about an objects ability to provide context when methods or operators are called on the object. Polymorphism In object-oriented programming, polymorphism (from the Greek meaning "having multiple forms") is the characteristic of being able to assign a different meaning to a particular symbol or "operator" in different contexts.

Polymorphism … class C {

class A { public: Virtual void f(){cout<<“A”<<endl;} }; class B : { public: virtual void f() { std::cout << "Hello std::endl;}; };

public: virtual void f() {std::cout << "Hello from C" << std::endl;}; };

from

B"

<<

If I have an object A, then calling the method f() will produce different results depending on the context, the real type of the object A. func(A & a) { };

a.f();

Polymorphism … Another growing concept in OOP is dynamic and static binding. Most languages provide one or the other. C++ provides both! A method that is not virtual is said to be statically bound, whereas virtual methods are said to be dynamically bound. Non-virtual methods are statically bound, because the binding of the method is performed at compile and link time and cannot be changed. Virtual methods are dynamically bound, because the binding of the method is actually performed at run-time. When you call a virtual method, a small lookup is performed in the object virtual table (a.k.a. vtable) to find the address of the method being called. By manipulating an objects vtable at run-time, the target address can be altered.

Vtable It is the table compiler generate as a reference to loader/liker that make desion of what offset to be selected. Let’s understand through some case codes studies: Vtable can be understood w.r.t two tables: 1. 2.

Code and call semantics Data layout

Vtable Table 1a: Example Code and Call Semantics Declarations

struct A { virtual void f (); virtual void g (); virtual void h (); int ia; };

Call

pa->f()

Callee

A::f()

Call Adjustment

none

Entry-point Adjustment

none

pa->g()

A::g()

none

none

pa->h()

A::h()

none

none

A *pa;

Vtable struct B: public virtual A { void f (); void h (); int ib;

pb->f()

B::f()

none

None

pb->A::f()

A::f()

none

none

pb->g()

A::g()

none

none

pb->h()

B::h()

none

none

pa_in_b->f()

B::f()

none

none

pa_in_b->g()

A::g()

none

none

pa_in_b->h()

B::h()

none

none

pa_in_b->A::f()

A::f()

none

none

};

B *pb; A *pa_in_b = pb;

Example data layout

Table 1b: Example Data Layout

Declarations

struct A { virtual void f (); virtual void g (); virtual void h (); int ia; };

Size

Offset

0

Member

A::vptr

16 8

ia

Note: Each function descriptor in the vtable is 16 bytes but the offset and data pointers are only 8, the earlier versions of this table didn't take that into account

struct B: public virtual A { void f (); void h (); int ib; };

0

B::vptr

8

ib

16

A::vptr

24

ia

0

C::vptr

8

ic

16

A::vptr

24

ia

32

struct C: public virtual A { void g (); void h (); int ic; };

32

Case study : Implementing a v-table

A() B() C()

Base-class region

Virtual function Used by derived

Derived-class region User control area

Compiler control area

Case study : Implementing a v-table … typedef (*fp)(); Class Base{ int basedata; public: Base(); virtual int A(); virtual int B(); virtual int C(); int Z(); }; Base::Base() {;;;;;;;;;;;;;;} int Base::A() { /*------*/} int Base::B() { /*------*/} int Base::C() { /*------*/} int Base::Z() { /*------*/}

void int int int int

Base__Base(){;;;;;;;;;;;;;;;} Base__A()(){/*----------*/} Base__B()(){/*----------*/} Base__C()(){/*----------*/} Base__D()(){/*----------*/}

fp virtual_Base[3] = { Base__A, Base__B, Base__C, }; struct class_Base { fp *vtab; int basedata; }

//vfTab

Case study : Implementing a v-table

struct class_Base s; //Allocate space Base__Base(&bobj) //call constructor &s is the implicit this pointer

int main() { Base bobj; bobj.Z(); bobj.A(); }

bobj.vtab = virtual_Base // Initialize a Vtab //the obj’s vft is initilized when the object created –at run time. The major diff b/w malloc and new Base__Z(&s); (*bobj.vtab[1])(&s)

Case study : Implementing a v-table typedef (*fp)(); Class D:public Base{ int ddata; public: D(); virtual int DA(); virtual int B(); }; D::D() int D::DA() int D::B()

{;;;;;;;;;;;;;;} { /*------*/} { /*------*/}

void D__D() {;;;;;;;;;;;;;;;} int D__DA() {/*----------*/} int D_B() {/*----------*/} //local B() fp virtual_D[3] = //vfTab { Base__A, D__B, Base__C, D_DA }; struct class_D { fp *vtab; int basedata; int ddata; }

Case study : Implementing a v-table: predict

Base *p = malloc(sizeof(D)); Base__Base(p) ; int main() {

D__D(p); Base d = new D; d->B() ;

p.vtab = virtual_D // D’s vtab

} //d->B (*s.vtab[1])(); // does as the earlier but with D’s call

Problems with a default virtual in derived class Class A {

public: virtual

void f() {printf(“A”);}

};

Class B:A {

public:

void f() {printf(“B”);}

};

Class C:B {

public:

void f() {printf(“C”);}

};

void main(){ A *ap = new A; ap->f(); ap = new B; ap->f(); ap = new C; ap->f(); B *bp = new B;

// works as expected

// calls B::f() // calls C::F() bp->f(); //calls B::f()

bp = new C; bp->f(); // dosen’t work as expected: calls B::f() as p is a B ptr and c !virtual }

Ending with Virtual destructors class base{ public: base(){} ~base(){} } class derived: public base{ public: derived{} ~deriver(){} } int main() { base *b; b = new derived; delete b; // calls only base’s destructor as p is a base*[] }

Abstraction Another OOP concept related to encapsulation that is less widely used but gaining ground is Abstraction. Through the process of abstraction, a programmer hides all but the relevant data about an object in order to reduce complexity and increase efficiency. In the same way that abstraction sometimes works in art, the object that remains is a representation of the original, with unwanted detail omitted. The resulting object itself can be referred to as an abstraction, meaning a named entity made up of selected attributes and behavior specific to a particular usage of the originating entity. The example presented is quite simple. Human's are a type of land animal and all land animals have a number of legs. The C++ definition of this concept would be...

Abstraction … class LandAnimal { public: virtual int NumberOfLegs()=0; }; class Human : public LandAnimal { public: virtual int NumberOfLegs() {return 2;}; }; The method NumberOfLegs in LandAnimal is said to be a pure virtual function. An abstract class is said to be any class with at least one pure virtual function. Here, we have created LandAnimal that is abstract.

a

class

It can be said that the LandAnimal class was abstracted from the commonality between all types of land animals, or at least those that I care about. Other land animals can derive there implementation from the same class. class Elephant : public LandAnimal { public: virtual int NumberOfLegs() { return 4; }; };

Abstraction … Although we cannot create an instance of the class LandAnimal, we can pass derived instances of the class to a common function without having to implement this function for each type of LandAnimal. bool HasTwoLegs(LandAnimal & x) { return (x.NumberOfLegs()=2); }; There is also a less rigid definition of abstraction that would include classes that without pure virtual functions, but that should not be directly instantiated. A more rigid definition of abstraction is called purely abstract classes.

A C++ class is said to be purely abstract, if the class only contains pure virtual functions. The LandAnimal class was such a class. Purely abstract classes are often called interfaces, protocol classes and abstract base classes.

Templates, generic function, class templates and function templates

Templates •Templates is C++ ‘s most sophisticated and high powered features •Although not a part of original specification to C++, it was added several years ago and is supported by all modern C++ compilers. •Using templates it is possible to create generic function and classes •In generic function or class the type of data upon which the function or class operates is specified as a parameter •Thus, we can use one function or class with several types of data without recoding specific version of each of them

Generic function •A generic function defines a general set of operation to various types of data •A generic function is created using the keyword template. •A normal meaning of template is seen as algorithm is independent of the data acting as a framework on with any data may act. •In essence, when you create a generic function you are creating a function that can automatically overload itself. It’s general format is Template fun-name(parameter list) { …….. }

Function template # include using namespace std; // This is a function template. template void swapargs (X &a, X &b) { X temp; temp = a; a = b; b = temp; int main ( ) { int i = 10, j = 20; double x = 10.1, y =23.3; char a = ‘x’, b = ‘z’;

Function template cout << “Original i, j:” << i <<’ ‘ << j << ‘\n’; cout << “Original x, y:” << x <<’ ‘ << y << ‘\n’; cout << “Original a, b:” << a <<’ ‘ << b << ‘\n’; swaprgs (i, j); // swap integers swaprgs (x, y); // swap floats swaprgs (a, b); // swap chars cout << “Swapped i, j:” << i <<’ ‘ << j << ‘\n’; cout << “Swapped x, y:” << x <<’ ‘ << y << ‘\n’; cout << “Swapped a, b:” << a <<’ ‘ << b << ‘\n’; return 0; }

Remember

// This will not compile.

// This will

template int i; void swapargs (X &a, Z &b) { X temp;

template

temp = a; a = b; b = temp; }

temp = a; a = b; b = temp; }

void swapargs (X &a, X&b) { X temp;

A function with two generic type # include using namespace std; template void myfunc (type1 x, type2 y) { cout << x << ‘ ‘ << y << ‘\n’; } int main ( ) { myfunc (10, “I like C++”); myfunc (98.6, 19L); return 0; }

Explicitly overloading a generic function // Overriding a template function # include using namespace std; template void swapargs (X &a, X &b) { X temp; temp = a; a = b; b = temp; cout << “Inside template swapargs.\n”; }

Explicitly overloading a generic function // This overrides the generic version of swapargs ( ) for ints. void swapargs (int &a, int &b) { int temp; temp = a; a = b; b = temp; cout << “Inside swapargs int specialization.\n”; }

Explicitly overloading a generic function int main ( ) { int i = 10, j = 20; double x = 10-.1, y = 23.3; char a = ‘x’, b = ‘z’;

cout << “Original i, j:” << i <<’ ‘ << j << ‘\n’; cout << “Original x, y:” << x <<’ ‘ << y << ‘\n’; cout << “Original a, b:” << a <<’ ‘ << b << ‘\n’; swapargs (i, j); // calls explicitly overloaded swapargs ( ) swapargs (x, y); // calls generic swapargs ( ) swapargs (a, b); // calls generic swapargs ( ) cout << “Swapped i, j:” << i <<’ ‘ << j << ‘\n’; cout << “Swapped x, y:” << x <<’ ‘ << y << ‘\n’; cout << “Swapped a, b:” << a <<’ ‘ << b << ‘\n’; return 0; }

Using Standard Parameters with Template Functions const int TABWIDTH = 8; // Display data at specified tab position. template void tabout (X data, int tab) { for (; tab; tab--) for (int i = 0; i
Generic Function Restrictions void myfunc (int i) { cout << “value is: “ << i << “\n”; } void myfunc (double d) { double intpart; double fracpart; fracpart = modf (d, &intpart); cout << “Fractional part: “ << fracpart; cout << “\n”; cout << “Integer part: “ << intpart; } int main ( ) { myfunc (1); myfunc (12.2); return o; } // templates cannot be applied for such situation as variant nature of a fun.

Class templates const int SIZE =10; \\ Create a generic stack class template class stack { StackType stck [SIZE]; // holds the stack int tos; // index of top-of-stack public : stack ( ) { tos = 0; } // initialize stack void push (StackType ob); // push object on stack StackType pop ( ); // pop object from stack };

Class templates …

// Push object. template void stack <StackType>:: push (StackType ob) { if (tos = =SIZE) { cout << “Stack is full./n”; return; } stck [tos] = ob; tos++; }

Class templates …

// pop an object. template StackType stack<StackType> : : pop ( ) { if (tos = = 0) { cout << “Stack is empty./n”; return 0; // return null on empty stack } tos--; return stck [tos]; }

Class templates … int main ( ) { // Demonstrate character stacks. stack s1, s2; // create two character stacks int i; s1.push (‘a’); s2.push (‘x’); s1.push (‘b); s2.push (‘y); s1.push (‘c’); s2.push (‘z); for (i=0; i<3; i++) cout << “Pop s1: “ <<s1.pop( ) << “\n”; for (i=0; i<3; i++) cout << “Pop s2 “ <<s2.pop( ) << “\n”; // demonstrate double stacks stack<double>ds1, ds2; // create two double stacks ds1.push (1.1); ds2.push (2.2); ds1.push (3.3); ds2.push (4.4); ds1.push (5.5); ds2.push (6.6); for (i=0; i<3; i++) cout << “Pop ds1: “ << ds1.po. ( ) << “ /n”; for (i=0; i<3; i++) cout << “Pop ds2: “ << ds2.po. ( ) << “ /n”; return 0; }

The typename keyword

•Recently these two keywords have been added to C++ specifically to templates. •The typename has two use •It can be substituted for the keyword class in template declaration •Another is: It informs compiler that the name is being used in a template declaration is a type rather than an object name.

Example

template void swapargs (X &a, X &b) { X temp; temp = a; a = b; b = temp; }

Exception Handling

Exception Handling: Fundamentals •Exception handling allows you to manage run-time errors •The principal advantage of EH is that it automates much of the error handling code that previously had to be coded in hand •C++ exception is built upon three keywords •Try •Throw •Catch •Try is the block where you will/can monitor your programs •If an exception occurs, it is thrown using throw •The exception is caught using the catch() and processed •Try should have a catch() immediately after the try’s block

Exception Handling: Fundamentals

Exception Handling … •The generic form of it: try{ // possibly expecting an error if the expected throw list-type; } // int x; will not work catch(type list) { } •Can have nested catches Try { ……….} catch(type1 list) { } Catch(type2 list) { }

A simple example # include using namespace std; int main ( ) { cout << “Start\n”; try { // start a try block cout << “Inside try block\n”; throw 100; // throw an error cout << “This will not execute”; } catch (int i) { // catch an error cout << “Cought an exception – value is: “; cout << i << “\n”; } cout << “End”; return 0; }

Multiple catches try { // start a try block cout << “Inside try block\n”; throw 100; // throw an error cout << “This will not execute”; } catch (int i) { // catch an error cout << “Cought an exception – value is: “; cout << i << “\n”; } catch (float i) { // catch an error cout << “Cought an exception – value is: “; cout << i << “\n”; } catch (char * i) { // catch an error cout << “Cought an exception – value is: “; cout << i << “\n”; }

Multiple catches void Xhandler (int test) { try { if (test) throw test; else throw Value is zero”; } catch (int i) { cout << “Caught Exception #: “ << i << ‘\n’; } catch (const char *str) { cout << “Caught a string: “; cout << str << ‘\n’; }} int main ( ) { cout << “Start\n”; Xhandler (1); Xhandler (2); Xhandler (0); Xhandler (3); cout << ‘End”; return 0; }

Exception Handling… •You can can any type of exception you want •Its general form is: Try { } Catch(…){ // any exception un-handled type will come here }

•You can re-throw an exception to outer block seeking if that can handle •It’s general form is Try { try{ if problem then throw } catch(type list) { // I will not /cannot handle hence throw list }} Catch(…) {}

Example: Catch Any type …

Int main() { try { } catch(…) { cout<<“Any thin will come here”; } }

Throwing an exception from a function outside the try block. void Xtest (int test) { cot << “Inside Xtest, test is: “ << test << “\n”; if (test) throw test; } int main ( ) { cout << “Start\n|; try { // start a try block cout << “Inside try block\n”; Xtest (0); Xtest (1); Xtest (2); } catch (int i) { // catch an error cout << “Caught an exception – value is: “; cout << i << “\n”; }

Restricting Exception Handling… •You can restrict an exception that a function can throw outside itself •Its general form is (arg-list) throw (int, char*) { // handles only whole numbers and strings } •Note: •if you throw any other type of exception then abnormal program termination would occur that internally calls a function unexpected() which by default calls terminate() •This restrictions apply only when you throw an exception outside a function. You may have inner try..catch within your function •You can similarly handle your own class type for all the above explained concept

Restricting function throw types. // This function can only throw ints, chars, and doubles. void Xhandler (int test) throw (int, char, double) { if (test ==0) throw test; // throw int if (test ==1) throw ‘a’; // throw char if (test ==2) throw 123.23; // throw double } int main ( ) { cout << “Start\n”;

Restricting function throw types.

try{ Xhandler (o); // also, try passing 1 and 2 to Xhandler ( ) } catch (int i) { cout << “Caught an integer\n”; } catch (char c) { cout << “Caught char/n”; } catch (double d) { cout << “Caught double /n”; }

Setting the terminate void my_Thandler() { cout<<"in my terminate"<<endl; } int main() { set_terminate(my_Thandler); try{ if something wrong throw ; } catch(type list) {// catch a type }

File Handling in C++

Hierarchy IOS

istream

ostream

fstreambase

iostream

ifstream

ofstream

FSTREAM

Operation under a file •A file is a collection of data stored with the secondary physical media. •The data storage differs in media and the standard file and I/O libraries takes care of bringing in to main memory[RAM] area. •This is the place data can be read,written, modified, appended, and deleted. •Accessing a file is done internally via device pointers that is maintained by system calls or device specific calls implemented under the OS you use. •These system calls are the wrappers build around those system calls that allow primarily the file operation you need to perform. •The I/O initialization is the most challenging job that provide a channel for open and close for any operation on file you want.

Operation under a file … •The file handling of C as we know is very powerful and based on its strength of library its widely popular and known to almost every one. •C++ behaves a bit differently as it deals with object behavior and tries to provide a easy way of handling file too! •C++ provides set of manipulation on data related to formatting stuff •You can do operations on both the types of data •Formatted (generally ASCII files are in this use) •Unformatted (Binary / raw data (no formatting present data) •You can use header for file based manipulation •For standard c++ I/O also is used

The first program #include using namespace std; int main() { ofstream SaveFile("cpp-file.txt"); //an object with constructor SaveFile << "Hello World!\n"; // writing via obj and << (default overloaded) SaveFile.close(); // calling close method to free the file descriptor return 0; }

Reading A File #include void main() //the program starts here { ifstream OpenFile("cpp-file.txt"); char ch; while(!OpenFile.eof()) { OpenFile.get(ch); cout << ch; } OpenFile.close(); } //The function eof() returns a nonzero value if the end of the file has been reached. So, we make a while loop, that will loop until we reach the end of the file

A useful reading #include void read(ifstream &T) //pass the file stream to the function { //the method to read a file, that I showed you before char ch; while(!T.eof()) { T.get(ch); cout << ch; } cout << endl << "--------" << endl; }

A useful reading …

void main() { ifstream T("file1.txt"); read(T); T.close(); T.open("file2.txt"); read(T); T.close(); }

Modes of operation ios::in

Open file to read

ios::out

Open file to write

ios::app

All the date you write, is put at the end of the file. It calls ios::out

ios::ate

All the data you write, is put at the end of the file.

ios::trunc

Deletes all previous content in the file. (empties the file)

ios::nocreate

If the file does not exists, opening it with the open() function gets impossible.

ios::noreplace

If the file exists, trying to open it with the open() function, returns an error.

ios::binary

Opens the file in binary mode.

In fact, all these values are int constants from an enumerated type. But for making your life easier, you can use them as you see them in the table.

Using modes file I/O

#include void main() { ofstream SaveFile("file1.txt", ios::ate); SaveFile << "That's new!\n"; SaveFile.close(); } Note: If you want to set more than one open mode, just use the OR operator- |. This way:

ios::ate | ios::binary

Read/Write at once #include void main() { fstream File("test.txt",ios::in | ios::out); File << "Hi!"; //put “Hi!” in the file static char str[10]; //when using static, the entire array is 0 File.seekg(ios::beg); //get to the beginning of file //seekg(-5) will take u 5 char back //this function is because default overloaded >> operator File >> str; cout << str << endl; File.close(); } Seekg is overloaded hence File.seekg(-5,ios::end);

Reading word by word

char str[30]; //the word can’t be more than 30 characters long

while(!OpenFile.eof()) { OpenFile >> str; cout << str; }

Reading line by line

char line[100]; //a whole line will be stored here while(!OpenFile.eof()) { OpenFile.getline(line,100); //where 100 is the size of the array

cout << line << endl; }

Check if the file opening was successful or not

Example 1: The most usual way

Xfstream File(“cpp-file.txt”); //X=i/o if (!File) { cout << “Error opening the file! Aborting…\n”;

exit(1); }

Check if the file opening was successful or not

Example 2: If the file is created, return an error

ofstream File("unexisting.txt", ios::nocreate);

if(!File) { cout << “Error opening the file! Aborting…\n”;

exit(1); }

Check if the file opening was successful or not

Example 3: Using the fail() function

ofstream File("filer.txt", ios::nocreate); if(File.fail()) { cout << “Error opening the file! Aborting…\n”; exit(1); } The new in Example 3, is the fail() function. It returns a nonzero value if any I/O error (not end of file) has occurred.

Handling Binary data [byte by byte] Example 1: Using get() and put() #include void main() { fstream File("test_file.txt",ios::out | ios::in | ios::binary); char ch; ch='o'; File.put(ch); //put the content of ch to the file File.seekg(ios::beg); //go to the beginning of the file File.get(ch); //read one character cout << ch << endl; //display it File.close(); }

Handling Binary data [block-wise data] Example 2: Using read() and write() #include #include <string.h> void main() { fstream File("test_file.txt",ios::out | ios::in | ios::binary); char arr[13]; strcpy(arr,"Hello World!"); //put Hello World! into the array File.write(arr,5); //put the first 5 symbols into the file- "Hello" File.seekg(ios::beg); //go to the beginning of the file static char read_array[10]; //I will put the read data, here File.read(read_array,3); //read the first 3 symbols- "Hel" cout << read_array << endl; //display them File.close(); }

Some useful functions

tellg() - Retunrs an int type, that shows the current position of the inside-pointer. This one works only when you read a file. tellp() - The same as tellg() but used when we write in a file. seekp() - Remember seekg()? we used it, when we was reading a file, and I wanted to go to specified position. seekp() is the same, but it is used when you write in a file. ignore(int count,char delimeter) - Used when reading a file. If you want to ignore certain amount of characters, just use this function. _unlink() - Deletes a file. Include io.h in your program, if you are going to use this function.

Creating you own inserters and extractors Inserters general form is: ostream &operator<<(ostream &stream, class_type type) { //… return stream; //should always return } Extractors general form is: istream &operator>>(istream &stream, class_type type) { //… return stream; //should always return }

Example Class phonebook{ public: char name[80]; int areacode; int prefix; int num; phonebook( char*n, int ac, int p, int nu) { strcpy(name,n); areacode = ac; prefix = p; num = nm; } friend ostream &operator <<(stream &stream,phonebook o); friend ostream &operator >>(stream &stream,phonebook &o) };

Example … ostream &operator <<(stream &stream,phonebook o) { stream<>(stream &stream,phonebook &o) { cout<<“Enter a name: ”; stream>>o.name ;

}

cout<<“Enter a areacode: ”;

stream>>o.areacode ;

cout<<“Enter a prefix: ”;

stream>>o.prefix ;

cout<<“Enter a number: ”; return stream;

stream>>o.num ;

Example …

int main() { phonebook a; cin>>a; cout<
return 0;

Run time type identification type_id, cast operators

RTTI

•C++ now supports RTTI and cast_operators. •Under nonpolymorphic languages it is not needed such as C. •RTTI were not the specification of STD C++ but both were added to C++ •The deterministic behavior of the calls under polymorphism is known under RTTI. •To obtain an obj’s type, we can use typeid. •Use to use the typeid •Typeid(object) •Typeid returns an reference to an object of type type_info that describes the type of object

typeid …

•The type_info class has following public members •bool •bool •bool •bool

operator ==(const type_info &obj); operator !=(const type_info &obj); before(const type_info &obj); char *name()

•The 1st two are for comparison operator for object similarity check •The before returns true if the invoking object is before the object used as a parameter in calling order. •Name() returns a pointer to the name of the type

typeid … int main() { int i,j; float f; char *p; Base bob; Derived dob; printf("typeid printf("typeid printf("typeid printf("typeid printf("typeid

of of of of of

i i i i i

is is is is is

%s\n",typeid(i).name()); %s\n",typeid(f).name()); %s\n",typeid(p).name()); %s\n",typeid(bob).name()); %s\n",typeid(dob).name());

typeid(i)== typeid(j)? printf("i==j.\n" ):printf("no idea.\n" ); typeid(i)== typeid(f)? printf("i==j.\n" ):printf("no idea.\n" ); typeid(p)== typeid(f)? printf("i==j.\n" ):printf("no idea.\n" ); typeid(bob)== typeid(dob)? printf("dob==bob.\n" ):printf("no idea.\n" ); }

typeid … class Base{

public: };

class Derived: public Base { public: void A(){} }; class Derived1: public Base { public: void A(){} };

virtual void A(){};

typeid … int main() { Base *bp,b; Derived d; Derived d1; bp=&b; printf("bp is now with %s\n",typeid(*bp). name()); bp=&d; printf("bp is now with %s\n",typeid(*bp). name()); bp=&d1; printf("bp is now with %s\n",typeid(*bp). name()); }

Cast operators There are four casting operators in C++ with their main usage: Type caster keyword and Description static_cast To convert non polymorphic types. const_cast To add or remove the const-ness or volatile-ness type. dynamic_cast To convert polymorphic types. reinterpret_cast For type conversion of unrelated types.

Using Cast operators •The syntax is same for the four type cast except the cast name: name_cast (expression)

where: name

either one of the static, const, dynamic or reinterpret

new_type

the result type of the cast.

expression

expression to be cast.

Static cast: Example int main() { int sum = 1000; int count = 21; double average1 = sum/count; cout<<"Before conversion = "<(sum)/count;

}

cout<<"After conversion = "<
Static cast: Example //enum data type enum color {blue, yellow, red, green, magenta}; int main() { int p1 = 3; cout<<"integer type, p1 = "< (p1)"<<endl; color c1 = static_cast (p1); cout<<"enum type, c1 = "<
return 0;

Constant cast: Example int main() { const int p = 20; cout<<"const p = "<
//const argument, cannot be modified... void funct2(const One& c) { //remove the const... One &noconst = const_cast (c); cout<<"The reference = "<<&noconst<<endl; noconst.funct1(); }

//c.funct1(); //uncomment the above and notice it

Constant cast: Example

int main() {

}

One b; funct2(b); return 0;

Dynamic cast: Example class Base1 {}; //derived class... class Derived1:public Base1 {}; //another derived class class Derived2:public Derived1{}; //dynamic_cast test function... void funct1() { //instantiate an object… Derived2* Test1 = new Derived2; //upcasting, from derived class to base class, //Derived1 is a direct from Base1 //making Test2 pointing to Derived1 sub-object of Test1 Derived1* Test2 = dynamic_cast(Test1); cout<<"Derived1* Test2 = dynamic_cast(Test1);"<<endl;

Dynamic cast: Example if(!Test2) cout<<"The conversion is fail..."<<endl; else cout<<"The conversion is successful..."<<endl; //upcasting, from derived class to base class //Derived2 is an indirect from Base1 Base1* Test3 = dynamic_cast(Test1); cout<<"\nBase1* Test3 = dynamic_cast(Test1);"<<endl; if(!Test3) cout<<"The conversion is fail..."<<endl; else cout<<"The conversion is successful..."<<endl;

} int main() { funct1(); return 0; }

Standard Templates Library in C++

Introduction: STL

•The Standard Template Library, or STL, is a C++ library of container classes, algorithms, and iterators; •It provides many of the basic algorithms and data structures of computer science. •The STL is a generic library, meaning that its components are heavily parameterized: •Almost every component in the STL is a template. •You should make sure that you understand how templates work in C++ as we have done before you use the STL.

A brief Introduction to STL •Containers and algorithms •Like many class libraries, the STL includes container classes: •Classes whose purpose is to contain other objects. •The STL includes the classes vector, list, deque, set, multiset, map, multimap, hash_set, hash_multiset, hash_map, and hash_multimap. •Each of these classes is a template, and can be instantiated to contain any type of object. •You can, for example, use a vector in much the same way as you would use an ordinary C array, except that vector eliminates the job of managing dynamic memory allocation by hand.

Related Documents

Cpp Slides
November 2019 31
Cpp
May 2020 23
Cpp
December 2019 37
Cpp
June 2020 25
Cpp
October 2019 39
Cpp-objet
May 2020 21