---
# System prepended metadata

title: CPP2- Orthodox Canonical class form
tags: [42-C++]

---

# Orthodox Canonical Form

Mastering the **Orthodox Canonical Form** is essential for writing solid C++ classes.
This form ensures your class behaves predictably, especially when **copied** or **assigned**.

---

### [Ref] CPP-ex00
Let me walk you through the **best practice implementation** of a class following this form. We'll focus on a class called `Fixed`, and we’ll:

- Follow **Orthodox Canonical Form** (aka **Rule of Three**),
- Use **initialization lists**,
- Ensure **safe copying and assignment**,
- Include **clear, maintainable logging** (optional but useful when learning).

---

## ✅ Orthodox Canonical Form — The "Rule of Three"

A class that **manages resources** (like dynamic memory, file handles, etc.), or **encapsulates internal state**, should implement:

1. A **default constructor**
2. A **copy constructor**
3. A **copy assignment operator**
4. A **destructor**

Even if it doesn't manage memory directly, this pattern is a **best practice** for clarity and maintainability.

---

## 📦 Fixed.hpp

```cpp
#ifndef FIXED_HPP
#define FIXED_HPP

#include <iostream>

class Fixed {
private:
    int _value;                  // Internal fixed-point value
    static const int _fractionalBits = 8; // Number of fractional bits (e.g., 8 for 256 precision)

public:
    Fixed();                              // Default constructor
    Fixed(const Fixed& other);            // Copy constructor
    Fixed& operator=(const Fixed& other); // Copy assignment operator
    ~Fixed();                             // Destructor

    int getRawBits() const;               // Getter
    void setRawBits(int const raw);       // Setter
};

#endif
```

---

## 🔧 Fixed.cpp

```cpp
#include "Fixed.hpp"

// Default constructor
Fixed::Fixed() : _value(0) {
    std::cout << "Default constructor called" << std::endl;
}

// Copy constructor
Fixed::Fixed(const Fixed& other) : _value(other._value) {
    std::cout << "Copy constructor called" << std::endl;
}

// Copy assignment operator
Fixed& Fixed::operator=(const Fixed& other) {
    std::cout << "Copy assignment operator called" << std::endl;
    if (this != &other) {
        this->_value = other._value;
    }
    return *this;
}

// Destructor
Fixed::~Fixed() {
    std::cout << "Destructor called" << std::endl;
}

// Getter
int Fixed::getRawBits() const {
    std::cout << "getRawBits member function called" << std::endl;
    return this->_value;
}

// Setter
void Fixed::setRawBits(int const raw) {
    this->_value = raw;
}
```

---

## ✅ Key Best Practices You’re Using

| Practice | Why It Matters |
|---------|----------------|
| **Initialization Lists** | Avoids default construction + reassignment. More efficient. |
| **Copy Constructor / Assignment Operator** | Enables proper copying. |
| **Self-assignment check** | Prevents bugs when assigning `a = a`. |
| **Destructor even if trivial** | Future-proof. Add custom cleanup if needed. |
| **Encapsulation (`private _value`)** | Keeps internal state safe and controlled. |
| **Static const member (`_fractionalBits`)** | Shared constant for all instances; good for precision configuration. |

---

## 🧠 Pro Tip: When to Use Rule of Five / Zero?

You used the **Rule of Three** — great start.

- Use **Rule of Five** if your class **allocates memory or manages external resources**, like using `new`, file handles, etc. Then you also need:
  - Move constructor
  - Move assignment operator

- Use **Rule of Zero** when your class has **no resource management** and just uses smart pointers or standard types like `std::vector`.

---
## The best to init variables in C++ common practice?

### ✅ **Best Practice: Use Initialization List in the Copy Constructor**

It is the **preferred professional standard** in C++.

**initializing members directly in the initializer list** is the preferred and most efficient way. Here’s why:

---

### 🔍 Why Initialization List Is Better

```cpp
// Preferred
Fixed::Fixed(const Fixed& other) : _value(other._value) {
    std::cout << "Copy constructor called" << std::endl;
}
```

### ❌ Instead of This (Less Ideal)

```cpp
Fixed::Fixed(const Fixed& other) {
    std::cout << "Copy constructor called" << std::endl;
    _value = other._value; // assignment after default construction
}
```

---

### ✅ Benefits of Using Initialization List

| Advantage | Explanation |
|----------|-------------|
| **Performance** | The member is constructed directly with the desired value — no temporary default value, no reassignment. |
| **Safety** | Ensures constant or reference members (if any) are initialized properly (they *must* be initialized in the list). |
| **Clarity** | Expresses intent: you're *initializing*, not *reassigning*. |
| **Consistency** | Aligns with how built-in types and classes like `std::string`, `std::vector`, etc., are initialized safely. |

---

### 🧠 Rule of Thumb

> **Always use initializer lists in constructors, especially for:**
> - Member variables of class or struct types
> - `const` members
> - References
> - Large or complex types (for performance)

---

