Topics: Templates Exceptions Lecture 05: More C++ Topics: Templates Exceptions
Part I. Templates A way to "generalize" a function or class. You pass parameters when using a function or creating a class. Often the compiler can deduce these.
Motivation Suppose we write a function that does a sort of an array of floats: void sort(float * L, int size); If we wanted to make a function that sorts an array of int's we'd have to duplicate the entire function, just changing the parameter type (and the type of any temporary variables) What about a list of strings? of Monsters? Copy/Paste == BAD Templates to the rescue! [Do an example in code]
Template Functions template <class T> void foo(T x) { T temp; // … } // elsewhere foo(5); // Create a version of foo with T = int foo(3.7); // Create a version of foo with T = double foo("ABC"); // Create a version of foo with T = ?? // Probably const char * foo(string("ABC")); // Create a version of foo with T = string foo<string>("ABC"); // Create a version of foo with T = string // and auto builds a string, passing the // const char * as an arg.
Templates Since template functions are created as necessary, it's not possible to put them in a .cpp file. So…you must put them only in a .h file.
Template specialization In certain cases, we need to provide a specialized version of a template [Use strings with the sort function] General syntax // General case template <class T> void foo() { /* … */ } // Specific version (strings only) template <> void foo<string>() { /* … */ }
Template classes You can make a template-ized class The attributes, return types, parameters, etc, can all use the template type T. template <class T> class Foo { public: void setValue(const T new_val) { mVal = new_val; } T getValue(); protected: T mVal; }; // External definition – still needs to be in a .h file. T Foo<T>::getValue() return mVal; }
Part II: Exceptions A way to indicate an error case. Will crash your program…unless you handle (catch) the exception. Two aspects: When writing code, throw an exception if you encounter an error case. When using other code, you can try to execute it and catch an error if it occurs.
Example float myDivide(float a, float b) { if (b == 0.0f) throw(15); return a / b; } int main() float x, y, z; cout << "Enter numerator: "; cin >> x; cout << "Enter denominator: "; cin >> y; try myDivide(x, y); catch (int err) if (err == 15) cout << "Division error!\n"; else cout << "Unknown error!\n";
Custom Exception types Integers aren't very descriptive. A better solution (?) class MyException { public: MyException(string file, int line, string desc) : mFile(file), mLine(line), mDesc(desc) {} void output() {cout << "[" << mFile << "@" << mLine; cout << "]: '" << mDesc << "'" << endl; } string mFile, mDesc; int mLine; }; // Somewhere in our code if ( /* ??? */ ) throw MyException(__FILE__, __LINE__, "Noob error!");
Custom Exception Types, cont. int main() { try // Some code that could fail } catch (int err) catch (MyException & err) err.output(); catch (...) // <- Valid C++ code cout << "An unhandled error!" << endl;