Skip to content

Files

Latest commit

Dec 30, 2024
4e84381 · Dec 30, 2024

History

History

ex01

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
Dec 30, 2024
Dec 30, 2024
Dec 30, 2024
Dec 30, 2024
Dec 30, 2024
Dec 30, 2024
Dec 30, 2024

Exercise 01: Forms and Advanced C++ Concepts

Core Concepts

1. Forward Declarations and Header Dependencies

Forward declarations help manage circular dependencies between classes:

// In Form.hpp
class Bureaucrat;  // Forward declaration

// In Bureaucrat.hpp
class Form;        // Forward declaration
  • Allows header files to reference each other
  • Reduces compilation dependencies
  • Helps prevent circular inclusion issues

2. Circular Dependencies

When two classes need to know about each other:

// Class A needs Class B
class A {
    B* b;  // Needs forward declaration of B
};

// Class B needs Class A
class B {
    A* a;  // Needs forward declaration of A
};

Solutions:

  • Forward declarations
  • Proper header organization
  • Minimal includes in header files

3. Const Correctness

Using const correctly in class design:

class Form {
private:
    const std::string   _name;          // Constant member
    const int          _gradeToSign;    // Constant member
public:
    std::string getName() const;        // Const member function
};

Benefits:

  • Prevents accidental modifications
  • Clarifies intent
  • Enables optimization

4. Member Initialization Lists

Proper initialization of constant members:

Form::Form(const std::string& name, int grade)
    : _name(name),         // Initialize const member
      _gradeToSign(grade)  // Initialize const member
{
    // Constructor body
}

Importance:

  • Required for const members
  • More efficient than assignment
  • Guarantees initialization order

5. Access Control in Class Design

Three levels of access:

class Form {
private:
    // Internal implementation details
    const std::string _name;

protected:
    // Available to derived classes
    bool _isSigned;

public:
    // Public interface
    void beSigned(const Bureaucrat& b);
};

6. Exception Safety

Different levels of guarantee:

  1. Basic Guarantee:

    • No resource leaks
    • Program in valid state
  2. Strong Guarantee:

    • Operation succeeds or no effect
    • No side effects if exception thrown
  3. No-throw Guarantee:

    • Operation never fails
    • Used in destructors

7. Design Patterns

Common patterns used in this exercise:

  1. RAII (Resource Acquisition Is Initialization):

    • Resources managed through object lifetime
    • Automatic cleanup in destructors
  2. Delegation Pattern:

    • Bureaucrat delegates form signing to Form class
    • Clear separation of responsibilities

8. Class Relationships

Different types of relationships:

  1. Association:

    • Bureaucrat uses Form
    • Loose coupling between classes
  2. Dependency:

    • Form depends on Bureaucrat for signing
    • One-way relationship

9. Immutable Objects

Implementing immutable attributes:

class Form {
private:
    const std::string _name;          // Immutable
    const int _gradeToSign;          // Immutable
    bool _isSigned;                  // Mutable state
};

Benefits:

  • Thread safety
  • Predictable behavior
  • Easier to reason about

10. Stream Output Formatting

Custom output formatting:

std::ostream& operator<<(std::ostream& os, const Form& form) {
    os << "Form: " << form.getName()
       << "\nStatus: " << (form.getIsSigned() ? "Signed" : "Unsigned");
    return os;
}

Features:

  • Chainable operations
  • Consistent formatting
  • Readable output

11. Code Organization Principles

  1. Separation of Concerns:

    • Each class has distinct responsibility
    • Clear boundaries between functionality
  2. Single Responsibility Principle:

    • Form handles form-related operations
    • Bureaucrat handles bureaucrat operations
  3. Interface Segregation:

    • Minimal public interfaces
    • Only necessary operations exposed

12. Error Handling Strategies

  1. Exception Classes:
class GradeTooHighException : public std::exception {
    const char* what() const throw() {
        return "Grade too high";
    }
};
  1. Error Checking:
void Form::beSigned(const Bureaucrat& b) {
    if (b.getGrade() > _gradeToSign)
        throw GradeTooLowException();
    _isSigned = true;
}