610 likes | 813 Views
Overview of C++. CS3304 - Data Structure. Value parameters. Value parameters int abc (int a, int b , int c) // a, b, and c are the { // formal parameters a = a * 2; return a+b+c; } call: z = abc(2, x, y) //2, x, y are the actual parameters. Template Functions.
E N D
Overview of C++ CS3304 - Data Structure
Value parameters • Value parameters int abc (int a, int b , int c) // a, b, and c are the { // formal parameters a = a * 2; return a+b+c; } call: z = abc(2, x, y) //2, x, y are the actual parameters
Template Functions float abc (float a, float b, float c) { a = 2 * a; return a+b+c; } template <class T> T abc(T a, T b, T c) { a = 2 * a; return a+b+c; }
Reference Parameters float abc(int& a, int& b, int& c) { a = 2 * a; return a+b+c; } template <class T> T abc (T& a, T& b, T& c) { a = 2 * a; return a+b+c; }
Const Reference Parameters • Formal parameters are not changed, avoid copying template < class T> T abc (const T& a, const T& b, cont T& c) { return a+b+c; } template <class Ta, class Tb, class Tc> Ta abc(const Ta& a, const Tb& b, const Tc& c) { return a+b+c }
Return Values • Value return T X(int i, T& z) // a copy of the value is returned • reference return T& X(int i, T& z) //a reference is returned • const reference return const T& X(int i, T& z) // a reference to a const // object is returned
Recursive functions When a function calls itself (directly or indirectly). ex: factorial, exponentiation, and Fibonacci numbers n! = 1 * 2 * 3 * ... *n, for n > 0 and that 0! = 1 a recursive function has two parts: · base part · recursive part
ex: Factorial n! = 1 if n = 0 (base) n! = n(n-1)! if n > 0 (recursive)
Definition • Recursion is a problem solving tool that allows you to solve a problem p by solving another problem p' that is similar in nature to p but smaller. • Each successive recursive call should bring you closer to a situation in which the answer is known. • A case for which the answer is known (and can be expressed without recursion) is called a base case. • Each recursivealgorithm must have at least one base case, as well as the general (recursive) case
Factorial N factorial n n! = n * (n - 1) * (n - 2) * ... * 2 * 1; int function fact (int n) { if (n == 0) // base case return (1); else // recursive case return (n * fact (n - 1)); }
Steps fact(4) -> 4 * fact(3) -> 3 * fact(2) -> 2 * fact(1) -> 1 * fact(0) 1 * 1 2 * 1 <-----------| 3 * 2 <-----------| 4 * 6 <------------| 24 <-------|
iterative solution to factorial int function fact_it (int n ) { int p; p = 1; for (int i = 1; i <= n; i++) p = p * i; return (p); }
Disadvantages and Advantages of recursion Disadvantages: each function call creates an activation record in memory & requires processing time to set up records & to reset values after return from function call advantages: some problems may be easier to set up & program
Iterative function for SUM Template <class T> T sum(T a[], int n) { //return sum of numbers a[0: n-1] T tsum = 0; for (int i = 0; i< n; i++) tsum += a[i] return tsum; }
Recursive function for SUM Template < calss T> T Rsum(T a[], int n) { // return sum of numbers a [0 : n-1] if (n > 0) return Rsum(a, n-1) + a[n-1] return 0; // base case }
Recursive function for the Fibonacci numbers • F(0) = 0 • F(1) = 1 • F(n) = F(n-1) + F(n-2) int fibonacci(int n) { if (n==0) return 0; else if (n==1) return 1; else if (n > 1) return (fibonacci(n-1) + fibonacci(n-2)); }
Dynamic Memory Allocation • Operator new int *y; y = new int; *y = 10; float *x = new float [n]; // array • Operator delete delete y; delete [] x; // one-dimensional array
The operator new int *y = new int; *y = 10 or int *y = new int (10) or int *y; y = new int (10)
One-Dimensional Arrays • Float *x = new float [n] • addressing the elements: • x[10], x[n-1]
Exception Handling • Using #Include <except.h> • using try and catch float *x; try {x = new float [n];} catch (xalloc) {// enter only when new fails cerr << “out of Memory” << endl; exit (1); } • xalloc exception is thrown by new when unable to allocate memory memory
Two-dimensional Arrays Char c[7][5] // static allocation • Dynamic allocation: char (*c) [5] // number of columns=5 try {c = new char [n][5];} // n is a variable catch (xalloc) { // enter only when new fails cerr << “out of Memory” << endl; exit (1); } • Value of n may be determined dynamically
Two-dimensional Arrays • What if number of columns is not known at compile time? • Need to construct array dynamically • View 2-d array as a 1-d array of rows • Each row is created using new • Pointers to each row are saved in another 1-d array. X
Pointer to Pointers template <class T> bool make2darray(T ** &x, int rows, int cols) { try { x = new T * [rows] // array of pointers // create memory for each row for (int i = 0, i <rows; i++) x[i] = new int [cols] return true } catch (xalloc) {return false;} }
Classes • Example: define a class currency • $2.35 • -$64.32 • Operations: • set data values • determine components • add two objects • increment the value • output
Classes enum sign (plus, minus); class Currency { private: sign sgn; unsigned long dollars; unsigned int cents; public: Currency(sign s = plus, unsigned long d = 0, unsigned int c = 0); ~Currency() {} bool Set(sign s, unsigned long d, unsigned int c); bool Set (float a);
Classes - cont. sign Sign() const {return sgn;} unsigned long Dollars() const {return dollars;} unsigned int Cents () cosnt {return cents;} Currency Add (const Currency& x) const; Currency& Increment (const Currency& x); void Output () const; }
Classes - cont. void main () { Currency f; currency g(plus, 2, 45), h(minus, 10); Currency *m = new Currency (plus, 8, 12); g.Set(minus, 33, 0); h.Set(78.33); }
Member Functions //Class constructor Currency::Currency(sign s, unsigned long d, unsigned int c) { if (c > 99) { cerr << “Cents should be < 100” << endl; exit (1);} sgn = s; dollars = d; cents = c; }
Member Functions - Cont. Bool Currency::Set(sign s, unsigned long d, unsigned int c) { if (c > 99 ) return false; sgn = s; dollars = d; cents = c; return true; }
Member function -cont Bool Currency::Set (float a) { if (a < 0) {sgn = minus; a = -a;} else sgn = plus; dollars = a; cents = ( a + 0.005 – dollars) * 100; return true; } //00.5 is needed to take care of computer errors when representing float numbers
Member function -cont Currency& Currency::Increment(const Currency& x) { *this = Add(x); return *this; } • this points to the invoking object • *this is the invoking object
Operator Overloading • C++ built-in operators can be overloaded • Overloaded operator obeys the precedence, associativity, and number of operands dictated by the built-in operator • When an operator is overloaded as a member function, the object associated with the operator is the left-most operand example: X + Y <=> X.operator + (Y) => left-most operand must be an object of the class of which the operator is a member. If that is not the case, instead of using a member operator use a friend operator.
Operator Overloading enum sign (plus, minus); class Currency { private: sign sgn; unsigned long dollars; unsigned int cents; public: Currency(sign s = plus, unsigned long d = 0, unsigned int c = 0); ~Currency() {} bool Set(sign s, unsigned long d, unsigned int c); bool Set (float a);
Operator Overloading sign Sign() const {return sgn;} unsigned long Dollars() const {return dollars;} unsigned int Cents () cosnt {return cents;} Currency operator+ (const Currency& x) const; Currency& Increment (const Currency& x); void Output () const; }
Operator Overloading Currency Currency::operator+ (const Currency& x) const { Currency y; y.amount = amount + x.amount; return y; } Example: Currency A(2, 50), B(minus, 7, 35), C; C = A + B;
Operator Overloading void Currency :: output() const { if (sgn == minus) cout << ‘-’; cout << ‘$’ << dollars << ‘.’; if (cents < 10) cout << “0”; cout << cents; } • Example: Currency X(plus, 3, 50); X.output();
Operator Overloading • Better overload the stream insertion operator <<: cout << X; • Note However, cout.operator << X // erroneous • the object from which the operator is invoked is not an object of type Currency. ==> operator << can NOT be a member of the class. • Can define operator outside the class ==> no access to private members • Define it as a friend member.
New Currency Class class Currency { friend ostream& operator<< (ostream&, const Currency&); public: Currency() …. Unsigned long Dollars() const { if (amount < 0) return (-amount) / 100; else return amount / 100;} …. Private: long amount; }
Member function -cont ostream& operator<< (ostream& out, const Currency& X) { if (X.sgn == minus) out << ‘-’; out << ‘$’ << x.dollars << ‘.’; if (X.cents < 10) out << “0”; out << X.cents; return out; }
Friend Functions/Operators • A friend function is a function defined outside of the class scope. Note: there is no scope resolution • The keyword “friend” is used in the class specification • A friend function of a class has access to the private members of the class • Inside the function definition, the dot operator is required to access the class data members.
Classes with Dynamic Data Members • Class constructor(s) • Class destructor • Class copy-constructor • Class deep copy function member
Classes with Dynamic Data Members • The following member functions are needed • Class constructor(s) • initialization • allocate space for dynamic data • Invoked automatically when an object is created • Class destructor • free space allocated for dynamic data • Invoked automatically when an object goes out of scope • Class copy-constructor • needed to do deep copying. Invoked automatically in the following situations • Initialization at declaration • An object parameter is passed by value • An object is the function return value • Class deep copy function member: Must be invoked explicitly
The Date Class Example class Date { public: Date(int, int, int, char* ); // Constructor Date(void ); // default Constructor Date(const Date& ) // Copy-constructor ~Date( void); // Destructor void DeepCopy (Date OtherDate); // Deep copy …. void get(int&, int&, int&); private: int month, day, year; char* msg; //pointer to char string };
Class Constructors Date::Date(void ) //default constructor { day = 1; month = 1; year = 1; msg = NULL; //msg points to NULL } Date::Date(int d, int m, int y, char* msgstr) { day = d; month = m; year = y; //Allocate memory for a new string of char msg = new char[strlen(msgstr) + 1]; //copy msgstr into msg strcpy(msg, msgstr); }
Class Constructors class Date { public: Date(int =1, int =1, int =1, char* =NULL ); //Constructor with default parameters Date(const Date& ) // Copy-constructor ~Date(void ); // Destructor void DeepCopy (Date OtherDate); //Deep copy void get(int&, int&, int&); private: int month, day, year; char* msg; //pointer to char string };
Class Constructors Example: Date X, Y(10, 5, 1995); Date Z(9, 2, 2002, "Labor Day"); Date A[100]; • When declaring an array of objects, the default constructor is used to initialize each object in the array. • If no default constructor (and no default parameters), the array objects will NOT be initialized.
Copy Constructor Needed to do deep copying. Invoked automatically in the following situations: • Initialization at declaration • An object parameter is passed by value • An object is a function return value
Copy Constructor class ClassName { public: ……… ClassName(const ClassName& SomeObject); private: ……… }; • A copy constructor is needed only if some data members are dynamic data • The name of the constructor is the same as the name of the class • The parameter is a reference to an object of the class type.
Date Copy-Constructor //Implementation of Date copy-constructor Date::Date(const Date& OtherDate) { // copy static data members month = OtherDate.month; day = OtherDate.day; year = OtherDate.year; //copy dynamic data member msg = new char[strlen(OtherDate.msg)+1]; strcpy(msg, OtherDate.msg); } Example: Date X(9, 2, 2002, "Labor Day"); Date Y= X; // Initialization at declaration