CS11 Advanced C++ Lecture 3 Spring 2012-2013Complex Numbers n Write a complex number class: class Complex { float real, imag; public: Complex(float re, float im) : real(re), imag(im) { } ... }; n Construct complex numbers like this: Complex a(2, 3); // 2 + 3i n What other ways to initialize complex numbers? Complex b; // 0 + 0i Complex c(5); // 5 + 0iDefault Values n Instead of creating multiple constructors, can specify default values for arguments class Complex { ... public: Complex(float re = 0, float im = 0) : real(re), imag(im) { } ... }; n Supports all desired call patterns: Complex a(2, 3); // Both re and im specified Complex b; // Both re and im default to 0 Complex c(5); // re = 5; im defaults to 0Rules for Default Values n Default values can only be specified once q Typically specified in declaration, not in definition n Arguments with default values must be at end of argument-list q This is invalid: void foo(int i, char *psz = 0, double x, int j = -1); q Move all default args to end: void foo(int i, double x, char *psz = 0, int j = -1);Rules for Default Values (2) n When calling a function with default values, can’t skip over some arguments q Only trailing arguments may be left unspecified n Continuing previous example: void foo(int i, double x, char *psz = 0, int j = -1); q This is invalid: foo(3, 2.25, , 15); // let psz default to 0 n These are the only valid call patterns: foo(3, 2.25); // psz = 0, j = -1 foo(3, 2.25, "hello"); // j = -1 foo(3, 2.25, "hello", 15); // no args unspecifiedFunction Pointers and Default Values n All arguments are part of a function’s type q …even those with default values n Example: void f(int i, int j = 0); ... void (*fp1)(int, int) = f; // OK void (*fp2)(int) = f; // COMPILE ERRORAnother Design Example n Create a 2D point class q Default coordinates to (0, 0) class Point { float x_coord, y_coord; public: Point(float x = 0, float y = 0) : x_coord(x), y_coord(y) { } ... }; n Do all valid call patterns make sense? Point a; // defaults to (0, 0) Point b(15, 2); Point c(3); // (3, 0) ???Default Arguments n When using default arguments, make sure that all valid call patterns make sense. n For 2D points, no reason to specify X coordinate and let Y default to 0. n Create two separate constructors: Point() : x_coord(0), y_coord(0) { } Point(float x, float y) : x_coord(x), y_coord(y) { } q Disallow the call-pattern Point(x)Class Members n Class-members are usually associated with objects class Matrix4F { float values[16]; public: ... bool isOrthogonal() { ... } }; q Each matrix-object has its own copy of values member q Calling isOrthogonal() requires a specific object Matrix4F m = ... ; if (m.isOrthogonal()) m.transpose(); // can invert by transposingStatic Members n Might want to provide constants for our class q Only want one copy of the constant for the entire class, not one per object! n Also might want to provide general utility functions for our class q Functions that help with the class, but don’t need to be called on a specific object n Static class-members aren’t associated with a specific object q The member is associated with the class itself, not with individual objectsStatic Constants n Add an Identity constant to our matrix class n Updated declaration, in our matrix.hh file: class Matrix4F { ... public: ... // Identity matrix constant static const Matrix4F Identity; }; n Static member is not defined or initialized in the declaration! q Separately initialized in corresponding matrix.cc file q (reasons are gross and involve compilation/linking issues)Static Constants (2) n Within the corresponding matrix.cc file: const Matrix4F Matrix4F::Identity = Matrix4F().setIdentity(); q Only use static keyword in declaration, not in definition q Refer to static member by its qualified name: Matrix4F::Identity n To use default initialization for static member: const Matrix4F Matrix4F::Identity; q Still must appear in the .cc file! Otherwise, linker errors… n Other code can refer to the static constant: #include "matrix.hh" if (m == Matrix4F::Identity) ...Static Functions n Add a static function to convert Euler angles into corresponding transform matrix class Matrix4F { ... public: ... static Matrix4F getEulerTransform( const EulerAngles &a); }; q Function definition can appear in class declaration or in definition q (only static member-variables are finicky)Static Functions (2) n Can call static function without requiring an object #include "matrix.hh" Matrix4F m; EulerAngles a; ... m = Matrix4F::getEulerTransform(a); q Use qualified name to refer to static member-function n Within the Matrix4F class definition, don’t need fully qualified name to refer to static memberC++ Templates n C++ supports both class templates and function templates n Example class template: template<typename T> class Point { T x_coord, y_coord; public: Point() : x_coord(0), y_coord(0) { } Point(T x, T y) : x_coord(x), y_coord(y) { } ... }; q Instantiate template as follows: Point<float> p1(3.31, 2.67); Point<int> p2(15, -6);Function Templates n Function templates are declared in a similar way: template <typename T> T square(T val) { return val * val; } q Squares its input q Works on any type that supports multiplication operator * n To use: int i = 15; cout << i << " squared = " << square(i) << endl; Matrix m(3, 3); // Matrix provides operator* Matrix m2 = square(m);Function Templates (2) n Function templates don’t require the template parameters to be specified! int i = 15; cout << i << " squared = " << square(i) << endl; Matrix m(3, 3); Matrix m2 = square(m); q Compiler figures it out from the function’s context n Function-template declaration: template <typename T> T square(T val) q When arg is an int, square is instantiated with T = int q When arg is a Matrix, square is instantiated with T = MatrixFunction Templates (3) n Can specify template parameters if you want: double
View Full Document