Understanding Function Templates and Generic Programming in C++

Slide Note
Embed
Share

Dive into function templates and generic programming in C++, exploring how to create reusable code for multiple data types. Learn about generic function templates, class templates, and how to declare function templates efficiently. Enhance your understanding of type-independent patterns and how to implement them effectively in your projects.


Uploaded on Jul 16, 2024 | 1 Views


Download Presentation

Please find below an Image/Link to download the presentation.

The content on the website is provided AS IS for your information and personal use only. It may not be sold, licensed, or shared on other websites without obtaining consent from the author. Download presentation by click this link. If you encounter any issues during the download, it is possible that the publisher has removed the file from their server.

E N D

Presentation Transcript


  1. 053 CS 45 OBJECT ORIENTED PROGRAMMING Degree 2ndSemester of second year By Dr. Prabakaran Narayanan Associate professor, CSISE DEPT

  2. TYPECASTING & DYNAMIC BINDING

  3. 3.1. Template Type-independent patterns that can work with multiple data types. Generic programming Code reusable Function Templates These define logic behind the algorithms that work for multiple data types. Class Templates These define generic class patterns into which specific data types can be plugged in to produce new classes.

  4. 4.2 Function and function templates C++ routines work on specific types. We often need to write different routines to perform the same operation on different data types. int maximum(int a, int b, int c) { int max = a; if (b > max) max = b; if (c > max) max = c; return max; } 4

  5. Function and function templates float maximum(float a, float b, float c) { float max = a; if (b > max) max = b; if (c > max) max = c; return max; } 5

  6. Function and function templates double maximum(double a, double b, double c) { double max = a; if (b > max) max = b; if (c > max) max = c; return max; } The logic is exactly the same, but the data type is different. Function templates allow the logic to be written once and used for all data types generic function. 6

  7. How to declare a function template? A function template starts with the keyword template followed by template parameter/s inside < > which is followed by function declaration. template <class T> T someFunction(T arg) { ... .. ... } In the above code, T is a template argument that accepts different data types (int, float), and class is a keyword. You can also use keyword typename instead of class in the above example. When, an argument of a data type is passed to someFunction( ), compiler generates a new version of someFunction() for the given data type.

  8. #include (iostream.h> Template < class T> T maximum(T a, T b, T c) { T max=a; if(b>max) if (c>max) return max; } Void main() { int x=30,y=67, z=8267; int x=maximum(x,y,z); //other data types double a=6.3, b=653.4, c=75.67; double sup= maximum(a,b,c); cout << The maximum number is << sup; } max=b; max=c

  9. template <typename T> void Swap(T &n1, T &n2) { Swapping of two numbers T temp; temp = n1; n1 = n2; n2 = temp; } int main() { int i1 = 1, i2 = 2; float f1 = 1.1, f2 = 2.2; char c1 = 'a', c2 = 'b'; cout << "Before passing data to function template.\n"; cout << "i1 = " << i1 << "\ni2 = " << i2; cout << "\nf1 = " << f1 << "\nf2 = " << f2; cout << "\nc1 = " << c1 << "\nc2 = " << c2; Swap(i1, i2); Swap(f1, f2); Swap(c1, c2); cout << "\n\nAfter passing data to function template.\n"; cout << "i1 = " << i1 << "\ni2 = " << i2; cout << "\nf1 = " << f1 << "\nf2 = " << f2; cout << "\nc1 = " << c1 << "\nc2 = " << c2; return 0; }

  10. 4.2. Generic Function Generic function to find a maximum value (see maximum example). template <class T> T maximum(T a, T b, T c) { T max = a; if (b > max) max = b; if (c > max) max = c; return max; } This function itself is incomplete because the compiler will need to know the actual type to generate code. So template program are often placed in .h or .cpp files to be included in program that uses the function. C++ compiler will then generate the real function based on the use of the function template. 10

  11. 4.2. Generic function Usage(cont..) After a function template is included (or defined), the function can be used by passing parameters of real types. Template <class T> T maximum(T a, T b, T c) int i1, i2, i3; Int m = maximum(i1, i2, i3); maximum(i1, i2, i3) will invoke the template function with T==int. The function returns a value of int type. 11

  12. Function Templates Usage Each call to maximum() on a different data type forces the compiler to generate a different function using the template. See the maximum example. One copy of code for many types. int i1, i2, i3; // invoke int version of maximum cout << "The maximum integer value is: " << maximum( i1, i2, i3 ); // demonstrate maximum with double values double d1, d2, d3; // invoke double version of maximum cout << "The maximum double value is: " << maximum( d1, d2, d3 ); 12

  13. 4.3 Class template So far the classes that we define use fix data types. Sometime is useful to allow storage in a class for different data types. See simplelist1 (a list of int type elements) example What if we want to make a simple list of double type? Copy paste the whole file and replace int with double Make use of typedef in C++, See simplelist2. Still need to change one line of code for a new type. 13

  14. Class template Function templates allow writing generic functions that work on many types. Same idea applies to defining generic classes that work with many types -- extract the type to be a template to make a generic classes. See simplelist 14

  15. How to declare a class template? template <class T> class className { ... .. ... public: T var; T someOperation(T arg); ... .. ... };

  16. Simple calculator using Class template // Program to add, subtract, multiply and divide two numbers using class template #include <iostream> template <class T> class Calculator { private: public: T num1, num2; Calculator(T n1, T n2) { } num1 = n1; num2 = n2; void displayResult() { } cout << "Numbers are: " << num1 << " and " << num2 << "." << endl; cout << "Addition is: " << add() << endl; cout << "Subtraction is: " << subtract() << endl; cout << "Product is: " << multiply() << endl; cout << "Division is: " << divide() << endl;

  17. T add() { return num1 + num2; } }; T subtract() { return num1 - num2; } T multiply() { return num1 * num2; } T divide() { return num1 / num2; } int main() { } Calculator<int> intCalc(2, 1); Calculator<float> floatCalc(2.4, 1.2); cout << "Int results:" << endl; intCalc.displayResult(); cout << endl << "Float results:" << endl; floatCalc.displayResult(); return 0;

  18. Outputs Int results: Numbers are: 2 and 1. Addition is: 3 Subtraction is: 1 Product is: 2 Division is: 2 Float results: Numbers are: 2.4 and 1.2. Addition is: 3.6 Subtraction is: 1.2 Product is: 2.88 Division is: 2

  19. 4.4 . Object serialization Serialization and objects on a support (a file, a buffer, a socket), so that they can be reconstructed later in the memory of the same or another computing host. consists of writing data The reconstruction process is also known as deserialization.

  20. 4.5 . Type Conversion A type cast is basically a conversion from one type to another. There are two types of type conversion: Implicit Type Conversion Also known as automatic type conversion . Done by the compiler on its own, without any external trigger from the user. Generally takes place when in an expression more than one data type is present. In such condition type conversion (type promotion) takes place to avoid lose of data. All the data types of the variables are upgraded to the data type of the variable with largest data type.

  21. 4.5.1. Implicit Type Conversion // An example of implicit conversion Output: x = 107 y = a z = 108.789001 #include <iostream.h> int main() { int x = 10; // integer x char y = 'a'; // character c // y implicitly converted to int. ASCII // value of 'a' is 97 x = x + y; // x is implicitly converted to float float z = x + 1.789; cout << "x = " << x << "y = " << y << "z = " << z } return 0;

  22. 4.5.2. Explicit Type Conversion Explicit Type Conversion: This process is also called type casting and it is user-defined. Here the user can typecast the result to make it of a particular data type.In C++, it can be done by two ways: Converting by assignment: This is done by explicitly defining the required type in front of the expression in parenthesis. This can be also considered as forceful casting. Syntax: (type) expression Where type indicates the data type to which the final result is converted.

  23. 4.5.2. Explicit Type Conversion #include<iostream.h> void main() { float x =90.765; int y = (int) x; cout << y; }

  24. 4.6.Casting operators A cast is a special operator that forces one data type to be converted into another. As an operator, a cast is unary and has the same precedence as any other unary operator. The most general cast supported by most of the C++ compilers is as follows Syntax: (type) expression Where type is the desired data type. There are other casting operators supported by C++, they are listed below

  25. const_cast<type> (expr) The const_cast operator is used to explicitly override const and/or volatile in a cast. The target type must be the same as the source type except for the alteration of its const or volatile attributes. This type of casting manipulates the const attribute of the passed object, either to be set or removed. dynamic_cast<type> (expr) The dynamic_cast performs a runtime cast that verifies the validity of the cast. If the cast cannot be made, the cast fails and the expression evaluates to null. A dynamic_cast performs casts on polymorphic types and can cast a A* pointer into a B* pointer only if the object being pointed to actually is a B object. reinterpret_cast<type> (expr) The reinterpret_cast operator changes a pointer to any other type of pointer. It also allows casting from pointer to an integer type and vice versa. static_cast<type> (expr) The static_cast operator performs a nonpolymorphic cast. For example, it can be used to cast a base class pointer into a derived class pointer.

  26. 4.7. Dynamic casting To use dynamic_cast<new_type>(ptr) the base class should contain at least one virtual function. dynamic casting is, primarily, used to safely downcast; i.e., cast a base class pointer (or reference) to a derived class pointer (or reference). It can also be used for upcasting; i.e., casting a derived class pointer (or reference) to a base class pointer (or reference). Dynamic casting checks consistency at runtime; hence, it is slower than static cast. Take a look at the function signature of the dynamic cast below:

  27. #include <iostream.h> class A { public: }; virtual void f(){cout << "A::f()" } class B : public A { public: }; void f(){cout << "B::f()" } int main() { A a; B b; a.f(); // A::f() b.f(); // B::f() A *pA = &a; B *pB = &b; pA->f(); // A::f() pB->f(); // B::f() pA = &b; // pB = &a; // not allowed pB = dynamic_cast<B*>(&a;); // allowed but it returns NULL } return 0;

  28. 4.8.Dynamic Binding C++ provides facility to specify that the compiler should match function calls with the correct definition at the run time; this is called dynamic binding or late binding or run-time binding. Dynamic binding is achieved using virtual functions. Base class pointer points to derived class object

  29. 4.9.RTTI (Run-time type Identification) in C++, RTTI (Run-time type information) is a mechanism that exposes information about an object s data type at runtime and is available only for the classes which have at least one virtual function. It allows the type of an object to be determined during program execution For example, dynamic_cast uses RTTI and following program fails with error cannot dynamic_cast `b (of type `class B* ) to type `class D* (source type is not polymorphic) because there is no virtual function in the base class B

  30. 4.9.RTTI (Run-time type Identification) // CPP program to illustrate // Run Time Type Identification #include <iostream.h> class B { }; class D: public B {}; int main() { } B *b = new D; D *d = dynamic_cast<D*>(b); if(d != NULL) cout<<"works"; else cout<<"cannot cast B* to D*"; getch(); return 0;

  31. THANK YOU

Related