Download presentation
Presentation is loading. Please wait.
Published byPhillip Blaze Fox Modified over 6 years ago
1
Function Overloading, Templated Functions, Templated Classes, Pointers to Functions
Horton pp. 247 – 254 (function overloading and templated functions) Tapestry Sect (for templated functions) Horton pp. 378 – 412 (templated classes with some advanced issues that we will not see) Tapestry Section (templated classes – more condensed) Horton pp. 231 – 237 (Pointers to Functions) Functors (Function Objects) are at the end of these slides, but we will skip them (not responsible)
2
Aim Sometimes you need variations of the same basic function: You can:
one function to sort an array of integers and another one to sort an array of characters one function to swap two variables of type int, another one to swap two variables of type char one function to find the maximum element of an array of ints, another one for an array of strings . . . You can: define two different functions with the same name but taking different types of arguments: function overloading 2. use a templated function which uses a templated type
3
Function overloading Define two different functions that take the appropriate parameter types: void Sort (vector<int> & a) void Sort (int a[], int size) {...} {...} void Sort (vector<string> & a) void Sort (string a[], int size) {...} {...}
4
Function overloading Define:
void Sort (vector<int> & a) {...} void Sort (vector<string> & a) The appropriate function will be called depending on the parameter. E.g. vector <int> nums; vector <string> names; sort(nums); //calls the first function sort(names); //calls the second function This may be the right solution in some cases. But function overloading duplicates code: maintaining is difficult (different versions of a sort function); if there is a change, you have to update all
5
Function overloading Also, you cannot do this with function overloading: int FindRoots(double a, double b, double c) double FindRoots(double a, double b, double c) Why? Because from the types of the parameters passed, you cannot determine which function should be called The signatures (parameters+function name) of two different functions should not be completely the same You cannot differentiate between two functions just using their return type
6
Templated functions writing a single instance of a function with generic type name
simple form for ints: void Swap(int & a, int & b) { int temp; temp = a; a = b; b = temp; } template <class Type> void Swap(Type & a, Type & b) { Type temp; temp = a; a = b; b = temp; } Any name can be the template parameter (e.g. Type, myType, sablonTipi, ...)
7
Not explicitly written but compiled in this way
Templated functions void Swap(double& a, double& b) { double temp; temp = a; a = b; b = temp; } template <class Type> void Swap(Type & a, Type & b) { Type temp; temp = a; a = b; b = temp; } int main() double d1, d2; cin >> d1 >> d2; Swap (d1, d2); string s1, s2; cin >> s1 >> s2; Swap (s1, s2); return 0; Not explicitly written but compiled in this way void Swap(string& a, string& b) { string temp; temp = a; a = b; b = temp; }
8
Templated functions: more complex
How can we swap the values at the given locations of a vector of any type? template <class T> void Swap(vector<T> & list, int i, int j) { T temp; temp = list[i]; list[i] = list[j]; list[j] = temp; } You can have a local variable of a templated type, but you should have at least one parameter of the same template type. In short, everywhere you had a element type (e.g. int), you put a new templated type name (e.g. T), and add template <class typename> at the beginning of the function.
9
Templated functions: more complex
template <class Type> void Print(const vector<Type> & list) { int i, count; count = list.Size(); for (i=0; i < count; i++){ cout << list[i] << endl; }
10
Templated functions: more uses and rules
template <class T> T DoStuff(T myvar) //template types can be return type, but there must be at least //one parameter of template type T doThis (int x) //this is not valid template <class noName> noName FindLastElement(vector<noName> & list1) //this is valid template <class T1, class T2> int CompareLists(vector<T1> & list1, vector<T2> & list2) //note that we have two templated types (T1 and T2) //in general you can have as many templated types as you need
11
function overload vs templated functions: comparison (Tapestry pp 543)
Function overloading duplicates code: maintaining is difficult (multiple versions of a function that does the same job for different parameter types) each must be changed if there is a need Function templates: reuses code, rather than to duplicate it causes code bloat: each instantiation of a function (i.e. each call to the function using a different type) adds new object code: that is why it is called template You should also consider reusing simple functions with type casting as a 3rd alternative, (when suitable) since in this case there is neither code duplication NOR code bloat! Define: void Swap (double & a, double & b ) Use with ints as: int a, b; Swap( (double)a, (double)b ); You can use this option when the task is suitable and –of course– types are easily convertable!
12
Templated Classes
13
Templated Classes Similar to the idea of a templated function, you can have templated classes. Main idea: types are not fixed at class declaration and definition; they are instantiated when the objects are created. Similar to templated functions, these provide type flexibility in class definitions. For instance, our linked list class contains ints in node. For nodes with strings, you need another class. This increases the size of the code. With the use of templated classes, we define the class and its implementation once and be able to be use it for integers or strings, etc. e.g. Tapestry's tvector and standart vector classes are templated classes vector<int> myintarr(1000); vector<string> mystrarr(1000);
14
Templated Classes It is a good idea to develop a non-templated version first, and then convert to a templated class later. Such a conversion is mostly changing the syntax of declarations and function/class headings by applying some simple rules. We will convert our previously developed LinkedList class with integer container to a templated class. But before that I will give a smaller example Normally what you have to do are as follows. add template <class itemType> before the class heading and before each member function implementation (not declaration). Here itemType is the element type that you store in a node. replace each of the occurrence of the element type with itemType everywhere in the class declaration (linkedlist.h file) and class implementation (linkedlist.cpp file). add <itemType> after the class name (in our case after LinkedList) in the class implementation file (linkedlist.cpp) – There is an exception for this rule for the constructors/destructor. See the example codes in the coming slides.
15
Templated Classes This procedure works fine if you do not use another templated class or templated struct in your class. If you define your struct within the class (as in the case of LinkStringSet class), again this procedure works. However, if you declare another templated class or a templated struct (in our case struct node) before your class, but want to use them in your class, you have to refer to these other structs/classes by adding <itemType> after the struct/class names everywhere (in both .h and .cpp files of your class). This is the case in our LinkedList example Structs can also be templated like classes (the rules are the same)
16
Templated Classes – Small Example
A class for Addition. Two private data members are added using + operator. Private data members are templates template <class OpType> class Add { public: Add (OpType op1, OpType op2); OpType operand (int i); OpType result (); private: OpType myOp1, myOp2; }; Add<OpType>::Add (OpType a, OpType b) :myOp1(a), myOp2(b) {} OpType Add<OpType>::operand (int i) { if (i==1) return myOp1; else if (i==2) return myOp2; } OpType Add<OpType>::result () { return myOp1 + myOp2; int main() { Add<int> a(5, 12); cout << a.operand(1) << " + " << a.operand(2) << " = " << a.result() << endl; Add<string> b("cs", "204"); cout << b.operand(1) << " + " << b.operand(2) << " = " << b.result() << endl; Add<char> c('2', '3'); cout << c.operand(1) << " + " << c.operand(2) << " = " << c.result() << endl; return 0; } In main, class is instantiated using three different types for OpType: int, string, char. What is output? See addtemplate.cpp = 17 cs = cs204 2 + 3 = e
17
Templated Classes – LinkedList class
First we need to convert the node struct to template template <class itemType> struct node { itemType info; node *next; node () { } node (const itemType & s, node * link) : info(s), next (link) };
18
Templated Classes – LinkedList class
Then the class definition is converted (LinkedListTemplate.h) template <class itemType> class LinkedList { private: node<itemType> * head; int size; public: LinkedList (); LinkedList (const LinkedList &); ~LinkedList (); void printList() const; void addToBeginning(itemType n); void deleteList (); const LinkedList & LinkedList::operator = (const LinkedList & rhs); node<itemType> * createClone () const; };
19
Templated Classes – LinkedList class
After that member functions are converted (LinkedListTemplate.cpp) Some examples here (see LinkedListTemplate.cpp for all) //copy constructor template <class itemType> LinkedList<itemType>::LinkedList (const LinkedList<itemType> & copy) { head = copy.createClone(); size = copy.size; } //destructor LinkedList<itemType>::~LinkedList () node<itemType> * ptr = head; while (ptr != NULL) node<itemType> * temp = ptr->next; delete ptr; ptr = temp; //constructor template <class itemType> LinkedList<itemType>::LinkedList () { head = NULL; size = 0; } For the constructors and destructor, add LinkedList<itemType> only for the left hand side of ::
20
Templated Classes – LinkedList class
template <class itemType> void LinkedList<itemType>::addToBeginning (itemType n) { node<itemType> *ptr = new node<itemType>(n,head); head = ptr; size++; } const LinkedList<itemType> & LinkedList<itemType>::operator = (const LinkedList<itemType> & rhs) if (this != &rhs) deleteList(); head = rhs.createClone(); size = rhs.size; return *this;
21
Templated Classes – LinkedList class
template <class itemType> node<itemType> * LinkedList<itemType>::createClone () const { if (head == NULL) return NULL; node<itemType> * headClone = new node<itemType> (head->info, NULL); node<itemType> * ptr = head->next; //second node in orig. node<itemType> * ptrClone = headClone; //to track the clone list while (ptr != NULL) ptrClone->next = new node<itemType> (ptr->info, NULL); ptr = ptr->next; ptrClone = ptrClone->next; } return headClone;
22
Templated Classes – LinkedList class Using in main
int main() { string baskan[] = {"Muharrem", "Aziz", "Dursun", "Fikret"}; LinkedList<string> strlist; //Linked list object with string element type LinkedList<int> intlist; //Linked list object with integer element type for (int k=0; k < 4; k++) strlist.addToBeginning(baskan[k]); intlist.addToBeginning(k+1); } cout << "string list contains:\n"; strlist.printList(); cout << "integer list contains:\n"; intlist.printList(); See linkedlisttemplate.h, linkedlisttemplate.cpp and linkedlisttemplatedemo.cpp
23
Templated Classes – LinkStringSet class
See Tapestry pp. 625 – 631 for the templated version of LinkStringSet class. Tapestry renamed templated version of this class as LinkSet Conversion to template is not different than what we have done for our LinkedList class, but in LinkSet class the Node struct definition is in the class definition. Thus Node struct is not templated and referral to node does not require to add <itemType> to the end. However, you have to refer to Node outside of the class definition by putting typename LinkSet<itemType>:: before Node The use of typename keyword is not mentioned in Tapestry, but it is needed in Visual Studio 2012 (also in some earlier versions of VS).
24
Fundemental Dilemma in using Templated Classes (Tapestry pp.628)
A templated class cannot be compiled without instantiating. The reason is simple, there is nothing to be compiled in the template itself! Even if you have both class declaration (.h) and class implementation in the same translation unit (which is the case in linkedlisttemplate.cpp since we include linkedlisttemplate.h at the beginning) compilation means nothing without knowing the corresponding real types for the templates. Compilation succeeds but does not produce the expected object code for the class member functions Thus when you use the class member functions in the main program, the linker will complain by some unresolved external symbol errors. Let us generate this case in our templated Linked List class. Types corresponding to templates become apparent when we generate objects in the main program. E.g. LinkedList <string> strlist; Thus, class declaration (linkedlisttemplate.h), member function implementations (linkedlisttemplate.cpp) and the user program (linkedlisttemplatedemo.cpp) must be in the same translation unit. There are some ways of doing this (see next slide)
25
Solutions to Fundemental Dilemma
Solution 1: Have both class declaration and implementation in the same file (name is not important but say .h file) and include it at the beginning of the user program file. Solution 2 (widely used): Keep separate .h (class declaration ) and .cpp (class implementation) files But at the end of the class header file (linkedlisttemplate.h) put #include "linkedlisttemplate.cpp" Include the header file (linkedlisttemplate.h) at the beginning of the user program, as usual. In this way, translation unit includes everything Caution 1: Do not add class implementation file (linkedlisttemplate.cpp) to the project; this would cause lots of redefinition errors. Caution 2: Since the header file is also included at the beginning of linkedlisttemplate.cpp (which actually is not needed in this approach), if you do not make the classical control to guard multiple header file inclusion you can have infinite inclusion. Thus you have to have the following structure in the header file: #ifndef _LINKEDLISTTEMPLATE_H #define _LINKEDLISTTEMPLATE_H // the class definition #endif Let's use this approach in our case Solution 3: Keep separate .h (class declaration ) and .cpp (class implementation) files and include both at the beginning of the user program
26
Function pointers
27
Function Pointers (Pointers to Functions)
Consider the following scenario: You have 2 or more functions with the same prototype other than their names i.e. they have same return types and same types for the parameters Example: double f1 (int, int, double); double f2 (int, int, double); . . . In another function (say myF), you want to call one of these functions, but you do not know which one while implementing myF So you want to make the "function to call" a parameter of myF and pass the actual function to call as an argument while you call myF Can you pass a function as parameter to another function? Yes, using pointers to functions.
28
See an example in funcptr.cpp
Pointers to Functions You can generate a pointer to a function using the following syntax Type (* PointerName)(Parameter list ) Type must match the function's return type Parameter list must match the function's parameter list Don't forget parentheses before and after * PointerName When you want to assign a function to a function pointer, you get the address of function using & and assign it to the function pointer: PointerName = & FunctionName; When you want to call the function using function pointer use: (* PointerName)(Argument list) See an example in funcptr.cpp
29
END OF THIS PPT SKIP THE REST (actually the rest of this ppt file is not shown in slide show mode since the rest of the slides are hidden)
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.