Skip to content

Teaching Notes: Module 02

  • Orthodox Canonical Form (OCF)
  • Copy constructor vs assignment operator
  • Operator overloading
  • Fixed-point number representation

  • Default constructor
  • Copy constructor
  • Copy assignment operator
  • Destructor
  • Basic getters/setters
  1. Confusing copy constructor and assignment

    Fixed a;
    Fixed b(a); // Copy constructor
    Fixed c = a; // Also copy constructor (initialization)!
    Fixed d;
    d = a; // Assignment operator (d already exists)
  2. Missing self-assignment check

    Fixed& operator=(const Fixed& other) {
    // Without this check, a = a; would be buggy
    if (this != &other) {
    _rawBits = other._rawBits;
    }
    return *this;
    }
  3. *Not returning this from assignment

    • Needed for chaining: a = b = c;
  • “When does the copy constructor get called vs the assignment operator?”
  • “Why do we return *this from the assignment operator?”
  • “What could go wrong if we don’t check for self-assignment?”

  • Converting from int/float to fixed-point
  • Converting from fixed-point to int/float
  • Stream insertion operator (<<)
Fixed-point with 8 fractional bits:
- Integer part: bits 31-8
- Fractional part: bits 7-0
To convert:
int -> fixed: value << 8
fixed -> int: value >> 8
float -> fixed: roundf(value * 256)
fixed -> float: value / 256.0f
  1. Wrong bit shifting direction

    • << shifts left (multiplies by 2^n)
    • >> shifts right (divides by 2^n)
  2. Forgetting to use roundf()

    • Float to fixed needs rounding for accuracy
  3. Integer division instead of float

    float toFloat() const {
    return _rawBits / 256; // WRONG - integer division!
    return _rawBits / 256.0f; // CORRECT
    }
  • “What does shifting left by 8 bits do mathematically?”
  • “Why do we need roundf() when converting from float?”
  • “How many values can 8 fractional bits represent between 0 and 1?”

  • Comparison operators
  • Arithmetic operators
  • Increment/decrement operators
  • Static member functions
// Pre-increment: ++a (returns new value)
Fixed& operator++() {
_rawBits++;
return *this;
}
// Post-increment: a++ (returns old value)
Fixed operator++(int) { // int is just a marker
Fixed temp(*this); // Save current
_rawBits++; // Increment
return temp; // Return old
}
  1. Return types for pre vs post increment

    • Pre: returns reference (efficient, can chain)
    • Post: returns copy (must, because returning old value)
  2. Epsilon value

    • Smallest representable value is 1 in raw bits
    • 1 / 256.0f = 0.00390625
  3. Arithmetic overflow

    • Multiplication: (a * b) >> 8
    • Division: (a << 8) / b
  • “Why does post-increment need to return a copy?”
  • “What’s the smallest value you can add to a fixed-point number?”
  • “How do you multiply two fixed-point numbers correctly?”

Exercise 03: BSP (Binary Space Partitioning)

Section titled “Exercise 03: BSP (Binary Space Partitioning)”
  • Using the Fixed class in practice
  • Point-in-triangle algorithm
  • const correctness
For triangle ABC and point P:
1. Compute cross product signs for:
- AB x AP
- BC x BP
- CA x CP
2. If all same sign (or zero) -> inside
3. If on edge (cross = 0) -> return false (per subject)
  1. Returning true for points on edges

    • Subject says: on edge or vertex = false
  2. Not handling const Fixed

    • Point attributes are Fixed const
  • “What does the cross product tell us about which side of a line a point is on?”
  • “Why might the subject want points on edges to return false?”

For every class from now on:

  • Default constructor
  • Copy constructor
  • Copy assignment operator (with self-assignment check)
  • Destructor
OperatorMember?Return Type
=MustT&
+, -, *, /UsuallyT
==, !=, <, >Eitherbool
++, -- (pre)MustT&
++, -- (post)MustT
<<Cannotostream&
  1. “Why is << not a member function?”

    • Because ostream is on the left side
    • We can’t modify ostream class
  2. “What’s the difference between copy constructor and assignment?”

    • Copy constructor: creates new object
    • Assignment: modifies existing object
  3. “Why Fixed-point instead of float?”

    • Predictable precision
    • No floating-point rounding errors
    • Faster on some hardware