800 Class Templates Templates are like advanced macros. They are useful for building new classes...

46
1 Class Templates Templates are like advanced macros. They are useful for building new classes that depend on already existing user defined classes or built-in types. Example: stack of int or stack of double Until compilers and linkers are integrated better, the template classes definitions as well as code are placed in header file. You include a template file (i.e. header file) in your source program. You should never compile a template file alone. member functions must be template functions.

Transcript of 800 Class Templates Templates are like advanced macros. They are useful for building new classes...

Page 1: 800 Class Templates Templates are like advanced macros. They are useful for building new classes that depend on already existing user defined classes or.

1

Class Templates• Templates are like advanced macros.• They are useful for building new classes that

depend on already existing user defined classes or built-in types.

• Example: stack of int or stack of double• Until compilers and linkers are integrated better,

the template classes definitions as well as code are placed in header file.

• You include a template file (i.e. header file) in your source program.

• You should never compile a template file alone.• member functions must be template functions.

Page 2: 800 Class Templates Templates are like advanced macros. They are useful for building new classes that depend on already existing user defined classes or.

2

An exampletemplate <class T1, class T2>class SomeNewClass{public: SomeNewClass(const T1& t1); ~SomeNewClass(); T1& SetData(const T2& t2, int n); :private: T1 a; T2 b;}Code for all functions are placed here.

Page 3: 800 Class Templates Templates are like advanced macros. They are useful for building new classes that depend on already existing user defined classes or.

3

Instantiation of Template class#include <somenewclass.h>int main(){ SomeNewClass<int,double> x; SomeNewClass<string,int> y; : :}

Compiler will create automatically two sets for functions based on the template code.

Page 4: 800 Class Templates Templates are like advanced macros. They are useful for building new classes that depend on already existing user defined classes or.

4

Template List Classtemplate <class ListItem>class List{public: List(); ~List(); bool IsEmpty(); void Insert(int pos, const ListItem& item, bool& success);

void Delete(int pos, bool& success); : :

Page 5: 800 Class Templates Templates are like advanced macros. They are useful for building new classes that depend on already existing user defined classes or.

5

Template List Class (contd)private: struct ListNode; typedef ListNode* ListNodePtr; struct ListNode { ListItem item; ListNodePtr next; };

ListNodePtr head; int size;}

Page 6: 800 Class Templates Templates are like advanced macros. They are useful for building new classes that depend on already existing user defined classes or.

6

Template List Class (contd)template <class ListItem>List<ListItem>::List(){ :}

template <class ListItem>List<ListItem>::Insert(int pos, const ListItem& item,

bool& success){ :}

Page 7: 800 Class Templates Templates are like advanced macros. They are useful for building new classes that depend on already existing user defined classes or.

7

Operator Overloading• Standard Operators in C++ can be overloaded to

have a different meaning when applied to operands of a new user defined class.

• The associativity or precedence of the operators remain the same.

• Operators such as + - * / = == < <= > >= | || & [] e.t.c. are all candidates for overloading.

• When overloading these operators we should maintain the intuitive meaning of these operators. We should also try to be consistent with their usage on built-in types.– a + b does not change a or b.– a = b, changes a but not b. It has value so that we

can do c = a = b;

Page 8: 800 Class Templates Templates are like advanced macros. They are useful for building new classes that depend on already existing user defined classes or.

8

Operators as member functions• If you define an operator using a member

function, then the left operand must be an object of the class for which the overloading is done.

• Operator funtions can be overloaded.• e.g. Complex a,b,c;

c = a + b; is same as c = a.operator+(b); whichin turn is same as c.operator=(a.operator+(b));

• Will c = a + 2 work?– Yes!! if Complex class has a constructor that takes

an integer as parameter. Compiler will create a temporary object using this constructor and add with a. Then the temporary object is destroyed. Thus, there is implicit casting done on rhs.

Page 9: 800 Class Templates Templates are like advanced macros. They are useful for building new classes that depend on already existing user defined classes or.

9

Operator as member function • Will c = 2 + a work?

– No!! Compiler will not cast 2 into Complex obj.– Casting is done only for function parameters, not

for the implicit object.• When you define a operator as member function,

the lhs operand MUST be an obj of the class.• The type of rhs operand can be anything as long as

you provide an operator function that takes that type or else there is a constructor function.

• Casting is done only if it can’t find a matching function. It is not a good idea to depend on casting. If there is more than one way to cast, it leads to confusion.

Page 10: 800 Class Templates Templates are like advanced macros. They are useful for building new classes that depend on already existing user defined classes or.

10

Operator as non-member function• It is also possible to define the operator functions

as non-member functions.• Non-member function do not have implicit

operand. Both operands are passed.• Both operands are defined as const ref parameters.• Non-member function can’t access private

variables of the class, unless it is defined as friend function inside the class (prototype).

• If non-member function is defined as friend, it serves as the prototype or else give an explicit prototype anyway.

• Avoid friend functions as much as possible.

Page 11: 800 Class Templates Templates are like advanced macros. They are useful for building new classes that depend on already existing user defined classes or.

11

Operator as non-member function• With non-member function operator+ will the

following work? – Complex a,b;– b = 2 + a;– Yes!! 2 will be cast as Complex object by compiler

• Non-member function is preferable to member functions when defining operators.

• Provide sufficient access functions in the class so that there is no need to give friend status to the function.

Page 12: 800 Class Templates Templates are like advanced macros. They are useful for building new classes that depend on already existing user defined classes or.

12

Operator Overloading (contd)class Foo{public: : bool operator<(const Foo& rhs) const; Foo operator+(const Foo& rhs) const; Foo& operator=(const Foo& rhs); bool operator==(const Foo& rhs) const; :}Note the use of const as necessary in defining the operator functions. For templates, Foo becomes, say Foo<T>.

Page 13: 800 Class Templates Templates are like advanced macros. They are useful for building new classes that depend on already existing user defined classes or.

13

operator =• The left hand side operand is the implicit object.• The left-hand side object is assigned the value of

right hand side object.• The code for operator= should first check for self-

assignment.• The code should also free the existing values for

left hand side object before copying rhs.• The return value should be a reference to the left

hand side object (which is implicit). This can be done by return(*this).

• The right hand side object should not change and hence is a const parameter.

Page 14: 800 Class Templates Templates are like advanced macros. They are useful for building new classes that depend on already existing user defined classes or.

14

Operator +• + means addition for numbers.• + can mean concatenation for strings.• + can mean Union for sets.• + can mean pair-wise addition for arrays or matrix• The return value must be a new object. • A local variable is needed to create the new object

before it can be returned.• return statement will invoke copy constructor.• Can be very inefficient if a large object creation

and copy is made. Inherent problem in C++.• We need to depend on compiler to optimize this.

Page 15: 800 Class Templates Templates are like advanced macros. They are useful for building new classes that depend on already existing user defined classes or.

15

Operator >>• We can define this operator so that we can read an

object using iostream. – e.g. Complex a; cin >> a;

• Notice that the lhs operand is not of type Complex• Member function is NOT possible.• Always pass iostream objects by reference. Not

even const (unless you don’t do io in the fn).• Invariably, these functions will need access to

private variables and hence the friend access may be needed for this function.

• The return value should be reference to the stream object passed.

Page 16: 800 Class Templates Templates are like advanced macros. They are useful for building new classes that depend on already existing user defined classes or.

16

mutable• Suppose we want to implement a class in which

we have some private variables that are used for efficiency but not quite associate with the class itself.– e.g. iterators for list use a private pointer curr.– string class can have two variables dataLength and

lengthValid flag to compute the length of string and store so that subsequent calls can use this for efficiency instead of recomputing. Length function uses these variables. Should Length be const fn?

• These functions should be allowed on const objects, but the compiler will not treat them as const functions. Soln: Define these variables as mutable.

Page 17: 800 Class Templates Templates are like advanced macros. They are useful for building new classes that depend on already existing user defined classes or.

17

Stream Input• Consider reading an integer from cin.

– int sum, m, n;– cin >> m >> n;– sum = 0;– while (cin >> m)– {– sum += m;– }

• The value of cin >> m should be cin itself so that we can read n in cin >> m >> n;

• What should the value of cin >> m in while loop?– If the value is cin, which is not NULL, it is always

true and hence the loop should be infinite!!!

Page 18: 800 Class Templates Templates are like advanced macros. They are useful for building new classes that depend on already existing user defined classes or.

18

Stream Input (Contd)• while loop expects an integer.• The steam class provides an operator to cast cin to

an int. That function ignores the pointer and returns the status of the stream (good or bad).

• The status of the stream should be bad after reading past end of file or after reading a bad input

• If the status of a steam is bad, no further input is possible until you clear the stream.

• When you open a file, if the file does not exist or it could not be opened, the stream is placed in a bad state. Thus, you cannot perform io. If you do, you will get garbage.

Page 19: 800 Class Templates Templates are like advanced macros. They are useful for building new classes that depend on already existing user defined classes or.

19

Stream Input (contd)• iostream has 4 bits.

– enum io_state { goodbit = 0x00, eofbit = 0x01, failbit = 0x02, badbit = 0x04 };

• Member Functions:– int good() -- All ok– int eof() -- stream encountered eof– int fail() -- operation not successful– int bad() -- operation invalid– int rdstate() -- read current state– void clear() -- restore to good state– int operator!(); true if fail or bad bit

is set. e.g. if (!cin) or if (! (cin >> n))

Page 20: 800 Class Templates Templates are like advanced macros. They are useful for building new classes that depend on already existing user defined classes or.

20

Operator>>• The operator>> is intended to read an object. If it

sees end of file or it sees bad input, it should place the stream in a bad state.

• It is possible that the stream is placed in a bad state when doing io to read a subpart of the object. In that case, there is nothing to do.

• If the input read does not meet the expectation, we want to place the stream in bad state by doing– fis.setstate(ios_base::failbit);

• To clear a stream, you can do– fis.clear();

Page 21: 800 Class Templates Templates are like advanced macros. They are useful for building new classes that depend on already existing user defined classes or.

21

Operator++ (or --)• ++ and -- are unary operators. The impicit object

is the operand. • Since there are two types: pre and post, we need a

way to distinguish between them.• The pre-increment operator for a class Foo is

written as– Foo& operator++();

• The post-increment operator for a class Foo is written as– Foo& operator++(int);– int argument is not used in the code and hence there is no need to specify the variable name.

Page 22: 800 Class Templates Templates are like advanced macros. They are useful for building new classes that depend on already existing user defined classes or.

22

Casting Operators• You can write casting operators for a class Foo so

that an object of type Foo can be converted to an object of another type.

• These are special member functions that have the syntax: operator <type>();– Note that there is no return type.– Note that there is no parameter.– class Foo { : operator int(); :}

– Foo a; int b; b = (int)a;– <type> can be any type. e.g. int *,void *, char *, double, etc.

Page 23: 800 Class Templates Templates are like advanced macros. They are useful for building new classes that depend on already existing user defined classes or.

23

operator []• This operator overloading is meaningful for an

object that has container objects. • [] can be used to retrieve individual objects.• For example, if we have a vector object, we can

access or change individual members.• The syntax is:

– <elemtype>& operator[](int index) const• The return value is a reference object which can be

used on lhs or rhs of an assignment statement.• The return type can include the keyword const to

prevent changes done on the object. Then, we can only retrieve the object but not change it.

Page 24: 800 Class Templates Templates are like advanced macros. They are useful for building new classes that depend on already existing user defined classes or.

24

Temporary Object• It is possible to create temporary objects that can

be useful in expressions. • These temporary objects are automatically created

and deleted by the compiler.• We can create a temporary object by simply using

the name of the class.• Let us say we have a class called Rational that has

a constructor function that takes an integer. Then, we can use it as follows:– Rational a(1,2), b(1,4), c;– c = a + b + Rational(2);– The value of c will be 1/2+1/4+2 = 2 3/4– c = (int) a; // Need operator int().

Page 25: 800 Class Templates Templates are like advanced macros. They are useful for building new classes that depend on already existing user defined classes or.

25

Inheritance• If you define a class based on a previously defined

class, the derived (or descendant) class is said to inherit many properties of the base (or ancestor) class.

• It is possible to have an hierarchy of classes arranged in a tree like structure.

• Inheritance describes the ability of a class to inherit information from ancestor classes.

• A class can be based on more than one base class in which case we are said to have multiple inheritance. We will avoid it in this course. It is complex and can lead to confusion if not used properly.

Page 26: 800 Class Templates Templates are like advanced macros. They are useful for building new classes that depend on already existing user defined classes or.

26

Why Inheritance?• Inheritance enables the reuse of existing classes.• Inheritance reduces the effort needed to add new

features to an existing object.• For example, we can have a class called Person

and then create a new class called Student and yet another class called Faculty both of which are derived from Person. Features that are common to both classes are placed in Person and hence reduces the need for duplication of information in classes.

• When an object is created for a class, it is also considered to be an object of all super classes.

Page 27: 800 Class Templates Templates are like advanced macros. They are useful for building new classes that depend on already existing user defined classes or.

27

What is inherited?• All member of the base class are inherited except

the constructors and destructors.• The derived class can add new members (both

variables and functions)• You cannot revise the ancestor’s members.• You can redefine member functions to have a

different meaning in a derived class.• You cannot redefine data members.• When an object is created, remember that we need

to initialize all variables and this will involve the constructor functions for ancestor classes.

Page 28: 800 Class Templates Templates are like advanced macros. They are useful for building new classes that depend on already existing user defined classes or.

28

Inheritance vs Access?• The derived class inherits the private variables of

the base class but cannot access them directly. Thus, we need to depend on constructor and member functions to deal with these variables.

• Inheritance does not mean accessibility.• The member functions of a derived class can call

public member functions of the base class.• The member functions of a derived class cannot

call private member functions of the base class.• What if a function name, say Foo, is common to

both classes? An object of a derived class will use the one in derived class and an object of the base class will use the one in base class.

Page 29: 800 Class Templates Templates are like advanced macros. They are useful for building new classes that depend on already existing user defined classes or.

29

Protected Members• A class can have protected members in addition to

public and private.• protected members are not accessible to clients of

the class.• protected members are accessible to derived class.• protected category helps to share information

among the classes in a single path of the hierarchy without sharing that information with other clients

• In general, one should place variables in private section. Place them in protected if it is essential to share them with derived classes.

Page 30: 800 Class Templates Templates are like advanced macros. They are useful for building new classes that depend on already existing user defined classes or.

30

Kinds of Inheritance• Public Inheritance:

– Both public and protected members of the base class remain public and protected members of the derived class. (i.e Keep same type of access)

• Protected Inheritance:– Both public and protected members of the base

class become protected members of the derived class.

• Private Inheritance:– Both public and protected members of the base

class become private members of the derived class.• Note that the derived class keeps the same access

or more stringent access (not more liberal access)

Page 31: 800 Class Templates Templates are like advanced macros. They are useful for building new classes that depend on already existing user defined classes or.

31

Data Initialization• Since the derived class inherits all data members

of the base class, we need to initialize them all.• When an object of the derived class is created, we

call the constructor function of the derived class.• The constructor function of the derived class will

automatically call the constructor function of the base class.

• Thus constructor functions are executed starting from the farthest ancestor to the derived class.

• Thus, a constructor function of a class is only responsible for initializing variables explicitly defined in that class not for those inherited.

Page 32: 800 Class Templates Templates are like advanced macros. They are useful for building new classes that depend on already existing user defined classes or.

32

Is-A Relationship• If you find that two classes share “is-a”

relationship, then it indicates that you can use public inheritance.

• An object of the derived class can be substituted for an object of the base class. (Object Type Compatibility).

• Thus, if a function expects a formal parameter to be of base type class, you can call it with derived class object.

• Object compatibility applies both to reference and value parameters.

• This leads to the issue of static vs dynamic (late) binding.

Page 33: 800 Class Templates Templates are like advanced macros. They are useful for building new classes that depend on already existing user defined classes or.

33

Has-A relationship• A ball-point pen has ball has its point. You

wouldn’t want to use a ball wherever a pen is expected!

• You may not even want to use inheritance here.• Make the ball as an object in the pen class. i.e it is

a member of the pen class.• has-a ==> containment• When an object of type pen is created, an object of

type ball is indirectly created and hence the constructor function for this should be called. This is done in the initializer list.

• Destructors are executed in reverse order.

Page 34: 800 Class Templates Templates are like advanced macros. They are useful for building new classes that depend on already existing user defined classes or.

34

As-A relationship• You can implement stack as a list.• When there is “as-a” relationship, consider private

inheritance.• Both “has-a” and “as-a” relationships are possible

when public inheritance in inappropriate.• When you have private inheritance, the public and

protected members of the base class become private and hence are not accessible to any new derived classes.

• “has-a” is the simplest to use and is preferable if it is sufficient for your needs.

Page 35: 800 Class Templates Templates are like advanced macros. They are useful for building new classes that depend on already existing user defined classes or.

35

Private Inheritance• If class D privately inherits from class B, then we

can say that “D is implemented in terms of B”.• Object of type D cannot be substituted for objects

of type B.• Private Inheritance means nothing during

Software Design, only during Software implementation.

• Private inheritance means that implementation only is inherited; interface should be ignored.

• Example: Suppose we implement stack in terms of list. Clearly an object of type Stack has a different interface from an object of type List. List is used only to implement Stack.

Page 36: 800 Class Templates Templates are like advanced macros. They are useful for building new classes that depend on already existing user defined classes or.

36

Inheritance Syntaxclass Ball: public Sphere{ :}class Ball: protected Sphere{ :}class Ball: private Sphere{ :}

Page 37: 800 Class Templates Templates are like advanced macros. They are useful for building new classes that depend on already existing user defined classes or.

37

Constructor UsageBall::Ball():Sphere(), ...{ :}

Ball::Ball(int n):Sphere(n),...{ :}

call the base class constructor

Page 38: 800 Class Templates Templates are like advanced macros. They are useful for building new classes that depend on already existing user defined classes or.

38

early binding• Let us assume that both Sphere and Ball classes

have a function called Display. • Consider the following examples:Sphere s1(3); Ball b1(4);Sphere *p = &s1; Sphere *q = &b1;s1.Display(); // early bindingb1.Display(); // early bindingp->Display(); // late binding? q->Display(); // late binding? Since p and q are pointers to Sphere, the last two calls will call Display in Sphere. Even the last one!!

Page 39: 800 Class Templates Templates are like advanced macros. They are useful for building new classes that depend on already existing user defined classes or.

39

Virtual Functions and Late Binding• In the previous example, if we defined Display in

Sphere class as a virtual function, then the last example will call the Display in Ball class rather than the one in Sphere class.

• Virtual keyword ==> Use the function in derived class if it has one.

• Assume that Display in sphere is declared as virtual.

Sphere *p = &s1; p->Display() will still call Display in Sphere as the object is an

instance of Sphere, not Ball. So, the question of considering Display in Ball does not even arise.

Page 40: 800 Class Templates Templates are like advanced macros. They are useful for building new classes that depend on already existing user defined classes or.

40

What is Late Binding?• Thus, the determination of which function to call

for a particular statement in the code is done at run time rather than during compiler time. This is known as “late” or “dynamic” binding.

• Dynamic binding is possible for functions declared as virtual.

• Thus a virtual function can be overridden in the derived class.

• The function Display is called “polymorphic”.• A polymorphic function has multiple meanings.• If you want the function in derived class to

override the one in base class, don’t forger virtual!

Page 41: 800 Class Templates Templates are like advanced macros. They are useful for building new classes that depend on already existing user defined classes or.

41

Omission of Virtual keyword• What happens if we omit virtual keyword?class Sphere{public: double Area() const; virtual Display() const; :}class Ball:public Sphere{public: double Area() const;}Ball class has Display function.

Page 42: 800 Class Templates Templates are like advanced macros. They are useful for building new classes that depend on already existing user defined classes or.

42

Omitting Virtual KeywordBall b(10);

b.Display(); Let us say Display calls Area().Since Area is not defined as virtual, the call to Area in Display will be interpreted by the compiler as the Area in Sphere (static binding). Thus the area function called will be the one in Sphere not the one in Ball.

If we had defined Area as virtual, then the Area() function call in Display will use late binding and will call correctly the Area in Ball class.

Page 43: 800 Class Templates Templates are like advanced macros. They are useful for building new classes that depend on already existing user defined classes or.

43

Virtual Method Table• The compiler creates a table for each class in

which it keeps track of the pointer to the actual function to be called for each virtual function defined in the class.

• VMT is invisible to the programmer as it is automatically created and managed by the compiler.

• A call to the constructor establishes this table.• Thus, VMT enables late (or dynamic) binding.

Page 44: 800 Class Templates Templates are like advanced macros. They are useful for building new classes that depend on already existing user defined classes or.

44

Abstract Class• When a class defines a virtual function, normally

the code for the function is also given.• Virtual function means, use the one in base class

unless it is overridden in the derived class.• Thus the code for the base class virtual function is

the most common use of the function. The code in derived classes are used to capture special cases.

• A base class can decide not to write the code for a virtual function. Thus, every derived class MUST provide one. Such a virtual function is called a pure virtual function.

• A class with at least one pure virtual function is called an abstract class. No instantiation allowed.

Page 45: 800 Class Templates Templates are like advanced macros. They are useful for building new classes that depend on already existing user defined classes or.

45

Abstract Class (contd)• Abstract classes are useful to build an hierarchy of

classes. • We do not create an instance (i.e an object) of an

abstract class. It is not allowed in C++.• You declare a virtual function as pure by using = 0

– virtual int Display() = 0;• If a class does not have any virtual function, it

means that it is meant to be used as a base class.• If a class has at least one virtual function, you

should normally declare the destructor as a virtual function too. It is highly recommended. If a class has no virtual function, don’t declare destructor function as virtual. Bad idea.

Page 46: 800 Class Templates Templates are like advanced macros. They are useful for building new classes that depend on already existing user defined classes or.

46

Destructors and Inheritance• When you have inheritance, the destructor

functions are called in reverse order.• What happens if we try to delete a derived class

object using a base class pointer? The compiler will call the destructors starting only from the base class going up in the hierarchy.

• But,we want to call destructors starting from the most specific class. The solution is to make the destructor function virtual in base classes.

• One twist: If you want to make a class abstract but you have no pure virtual functions, what do you do? Make the destructor a pure virtual function. But, you must provide code for this destructor fn.