17 structs and classes i
play

17. Structs and Classes I C++ does not provide a built-in type for - PowerPoint PPT Presentation

Calculating with Rational Numbers Rational numbers ( ) are of the form n d with n and d in 17. Structs and Classes I C++ does not provide a built-in type for rational numbers Goal Rational Numbers, Struct Definition, Overlading Functions


  1. Calculating with Rational Numbers Rational numbers ( ◗ ) are of the form n d with n and d in ❩ 17. Structs and Classes I C++ does not provide a built-in type for rational numbers Goal Rational Numbers, Struct Definition, Overlading Functions and We build a C++ -type for rational numbers ourselves! Operators, Const-References, Encapsulation 577 578 Vision A First Struct Invariant: specifies valid How it could (will) look like value combinations (infor- struct rational { mal). // input int n; std::cout << "Rational number r =? "; member variable ( n umerator) int d; // INV: d != 0 rational r; std::cin >> r; }; std::cout << "Rational number s =? "; member variable ( d enominator) rational s; std::cin >> s; struct defines a new type formal range of values: cartesian product of the value ranges of // computation and output existing types std::cout << "Sum is " << r + s << ".\n"; real range of values: rational � int × int . 579 580

  2. Accessing Member Variables A First Struct: Functionality A struct defines a new type , not a variable ! struct rational { int n; // new type rational int d; // INV: d != 0 struct rational { Meaning: every object of the new type is rep- }; int n; resented by two objects of type int the ob- int d; // INV: d != 0 jects are called n and d . rational add (rational a, rational b) }; { rational result; // POST: return value is the sum of a and b result.n = a.n ∗ b.d + a.d ∗ b.n; rational add (const rational a, const rational b) result.d = a.d ∗ b.d; { return result; rational result; } result.n = a.n * b.d + a.d * b.n; = a n · b d + a d · b n result.d = a.d * b.d; r n := a n + b n member access to the int objects of a . return result; r d a d b d a d · b d } 581 582 Input Vision comes within Reach ... // Input r rational r; std::cout << "Rational number r:\n"; std::cout << " numerator =? "; // computation std::cin >> r.n; const rational t = add (r, s); std::cout << " denominator =? "; std::cin >> r.d; // output std::cout << "Sum is " << t.n << "/" << t.d << ".\n"; // Input s the same way rational s; ... 583 584

  3. Struct Definitions Struct Defintions: Examples name of the new type (identifier) struct T { struct rational_vector_3 { T 1 name 1 ; rational x; names of the underlying names of the member T 2 name 2 ; rational y; types variables . . rational z; . . . . }; T n name n ; } ; underlying types can be fundamental or user defined Range of Values of T : T 1 × T 2 × ... × T n 585 586 Struct Definitions: Examples Structs: Accessing Members struct extended_int { expression of struct-type T name of a member-variable of type T . // represents value if is_positive==true // and − value otherwise expression of type T k ; value is the value of unsigned int value; expr.name k the object designated by name k bool is_positive; }; member access operator . the underlying types can be different 587 588

  4. Structs: Initialization and Assignment Structs: Initialization and Assignment Default Initialization: Initialization: rational t; rational t = {5, 1}; Member variables of t are default-initialized Member variables of t are initialized with the values of the list, for member variables of fundamental types nothing happens according to the declaration order. (values remain undefined) 589 590 Structs: Initialization and Assignment Structs: Initialization and Assignment = add (r, s) .n t.n ; t.d .d Assignment: Initialization: rational s; rational t = add (r, s); ... rational t = s; t is initialized with the values of add(r, s) The values of the member variables of s are assigned to the member variables of t . 591 592

  5. Structs: Initialization and Assignment Structs: Initialization and Assignment rational s; member variables are uninitialized Assignment: member-wise initialization: rational t = {1,5}; t.n = 1, t.d = 5 rational t; rational u = t; member-wise copy t = add (r, s); t = u; member-wise copy t is default-initialized The value of add (r, s) is assigned to t rational v = add (u,t); member-wise copy 593 594 Comparing Structs? Structs as Function Arguments void increment(rational dest, const rational src) { dest = add (dest, src ); // modifies local copy only For each fundamental type ( int, double,... ) there are } comparison operators == and != , not so for structs! Why? Call by Value ! member-wise comparison does not make sense in general... ...otherwise we had, for example, 2 3 � = 4 rational a; 6 rational b; a.d = 1; a.n = 2; b = a; increment (b, a); // no effect! std :: cout << b.n << "/" << b.d; // 1 / 2 595 596

  6. Structs as Function Arguments User Defined Operators void increment(rational & dest, const rational src) { dest = add (dest, src ); Instead of } rational t = add(r, s); we would rather like to write Call by Reference rational t = r + s; rational a; rational b; a.d = 1; a.n = 2; This can be done with Operator Overloading . b = a; increment (b, a); std :: cout << b.n << "/" << b.d; // 2 / 2 597 598 Overloading Functions Function Overloading A function is defined by name, types, number and order of arguments double sq (double x) { ... } // f1 int sq (int x) { ... } // f2 Functions can be addressed by name in a scope int pow (int b, int e) { ... } // f3 It is even possible to declare and to defined several functions int pow (int e) { return pow (2,e); } // f4 with the same name the compiler automatically chooses the function that fits “best” for a function the “correct” version is chosen according to the signature of the call (we do not go into details) function. std::cout << sq (3); // compiler chooses f2 std::cout << sq (1.414); // compiler chooses f1 std::cout << pow (2); // compiler chooses f4 std::cout << pow (3,3); // compiler chooses f3 599 600

  7. Operator Overloading Adding rational Numbers – Before // POST: return value is the sum of a and b rational add (rational a, rational b) Operators are special functions and can be overloaded { rational result; Name of the operator op : result.n = a.n ∗ b.d + a.d ∗ b.n; operator op result.d = a.d ∗ b.d; we already know that, for example, operator+ exists for different return result; types } ... const rational t = add (r, s); 601 602 Adding rational Numbers – After Other Binary Operators for Rational Numbers // POST: return value is the sum of a and b // POST: return value is difference of a and b rational operator+ (rational a, rational b) rational operator − (rational a, rational b); { rational result; // POST: return value is the product of a and b result.n = a.n ∗ b.d + a.d ∗ b.n; rational operator ∗ ( rational a, rational b); result.d = a.d ∗ b.d; return result; // POST: return value is the quotient of a and b } // PRE: b != 0 ... rational operator/ (rational a, rational b); const rational t = r + s; infix notation 603 604

  8. Unary Minus Comparison Operators are not built in for structs, but can be defined has the same symbol as the binary minus but only one argument: // POST: returns true iff a == b // POST: return value is − a bool operator== (rational a, rational b) rational operator − (rational a) { { return a.n ∗ b.d == a.d ∗ b.n; a.n = − a.n; } return a; 2 3 = 4 } � 6 605 606 Arithmetic Assignment Operator += First Trial rational operator+= (rational a, rational b) We want to write { a.n = a.n ∗ b.d + a.d ∗ b.n; rational r; a.d ∗ = b.d; r.n = 1; r.d = 2; // 1/2 return a; } rational s; does not work. Why? s.n = 1; s.d = 3; // 1/3 r += s; The expression r += s has the desired value, but because the arguments are std::cout << r.n << "/" << r.d; // 5/6 R-values (call by value!) it does not have the desired effect of modifying r . The result of r += s is, against the convention of C++ no L-value. 607 608

  9. Operator += In/Output Operators rational& operator+= (rational& a, rational b) can also be overloaded. { a.n = a.n ∗ b.d + a.d ∗ b.n; Before: a.d ∗ = b.d; return a; std::cout << "Sum is " } << t.n << "/" << t.d << "\n"; this works After (desired): The L-value a is increased by the value of b and returned as std::cout << "Sum is " L-value << t << "\n"; r += s; now has the desired effect. 609 610 In/Output Operators Input // PRE: in starts with a rational number can be overloaded as well: // of the form "n/d" // POST: r has been read from in // POST: r has been written to out std::istream& operator>> (std::istream& in, std::ostream& operator<< (std::ostream& out, rational& r) rational r) { { char c; // separating character ’/’ return out << r.n << "/" << r.d; return in >> r.n >> c >> r.d; } } writes r to the output stream reads r from the input stream and returns the stream as L-value. and returns the stream as L-value. 611 612

Recommend


More recommend