# Object Model and Memory Management Reference counting smart pointers and object lifecycle management following specific inheritance patterns. ## Core Concepts Always use `struct` for value types and `class` for reference types. All reference types must inherits from `Object` or other reference types. All interface types must virtual inherits from `Interface` or other interface types. A reference type must virtual inherits an interface type to implement it. ## Ptr - Smart Pointer Prefer `Ptr` to hold an initialized reference type instead of using C++ pointers, e.g. `auto x = Ptr(new X(...));`. `Ptr` is similar to `std::shared_ptr`. There is no `std::weak_ptr` equivalent constructions, use raw C++ pointers in such cases, but you should try your best to avoid it. ### Basic Usage ```cpp // Creating a Ptr auto obj = Ptr(new MyClass(...)); // Assignment and copying Ptr another = obj; // Reference counting // Checking if empty if (obj) { // Ptr is not empty } if (obj == nullptr) { // Ptr is empty } ``` ### Type Conversion If `T*` could be implicitly converted to `U*`, `Ptr` could be initialized with `Ptr`. If `T*` could be `dynamic_cast` to `U*`, use `Cast()` method instead. ```cpp Ptr base = Ptr(new DerivedClass(...)); Ptr derived = base.Cast(); ``` ### Resetting To reset a `Ptr`, assign it with `{}` or `nullptr`. ```cpp obj = {}; // Reset to empty obj = nullptr; // Reset to empty ``` ## ComPtr - COM Object Pointer `ComPtr` is similar to `Ptr` but it is for COM objects with Windows API only. ```cpp ComPtr comObj = ...; ``` ## Nullable - Optional Value Types `Nullable` adds `nullptr` semantics to value types. `Nullable` can be assigned with `T`, it becomes non-empty, otherwise it is empty. ### Basic Operations ```cpp Nullable value; // Empty by default value = 42; // Now contains 42 // Checking if empty if (value) { // Has value vint actual = value.Value(); } // Resetting to empty value.Reset(); // Comparison Nullable other = 42; if (value == other) { // Equal comparison } ``` ### Key Methods - **`Reset()`**: Makes the nullable empty - **`operator bool`**: Returns true if non-empty - **`Value()`**: Returns the contained value (only call if non-empty) The `Value()` method can only be called if you are sure it is non-empty, and it returns the value inside it. `Value()` returns a immutable value, you can't change any data inside value, but you can assign it with a new value. A `Nullable` can be compared with another one in the same type in the standard C++ way. ## Inheritance Patterns ### Reference Types (class) ```cpp class MyRefType : public Object { // Reference type implementation }; ``` ### Interface Types (class) ```cpp class IMyInterface : public virtual Interface { public: virtual void DoSomething() = 0; }; ``` ### Implementing Interfaces ```cpp class MyImplementation : public Object, public virtual IMyInterface { public: void DoSomething() override { // Implementation } }; ``` ### Multiple Interface Inheritance ```cpp class IAdvancedInterface : public virtual IMyInterface { public: virtual void DoAdvancedThing() = 0; }; ``` ## Special Cases ### Exception Classes Use `class` for defining new `Error` or `Exception` sub classes, although they are value types. ```cpp class MyCustomError : public Error { public: MyCustomError(const WString& message) : Error(message) {} }; ``` ### Function and Event Types `Func` and `Event` are also classes, although they are value types. ### Collection Types Collection types are also value types, although they implements `IEnumerable` and `IEnumerator`. This is also a reason we always use references instead of pointers on `IEnumerable` and `IEnumerator`. ### Struct in Ptr When really necessary, a struct could be used in `Ptr` for sharing. But prefer `Nullable` when `nullptr` is helpful but sharing is not necessary. ```cpp struct SharedData : public Object { vint value; WString name; }; Ptr sharedPtr = Ptr(new SharedData{42, L"Hello"}); ``` ## Memory Management Best Practices ### Reference Counting - `Ptr` uses reference counting for automatic memory management - Objects are automatically deleted when the last `Ptr` is destroyed - No need for manual memory management in most cases ### Avoiding Circular References Since there's no weak pointer equivalent, be careful of circular references: ```cpp // Potential circular reference problem class Parent : public Object { public: List> children; }; class Child : public Object { public: Ptr parent; // This can create cycles }; ``` Use raw pointers for back-references when appropriate: ```cpp class Child : public Object { public: Parent* parent; // Raw pointer to avoid cycles }; ``` ### Value vs Reference Types - **Use `struct`**: For value types (simple data containers, POD types) - **Use `class`**: For reference types (complex objects, polymorphic types) - **Inherit from `Object`**: All reference types - **Virtual inherit from `Interface`**: All interface types ## Extra Content ### Thread Safety `Ptr` reference counting is thread-safe, meaning multiple threads can safely copy and destroy `Ptr` instances. However, the pointed-to object itself is not automatically thread-safe. ### Performance Considerations - Reference counting has overhead compared to raw pointers - `Ptr` creation and destruction involve atomic operations - Consider using raw pointers for temporary references within a single function - Use `Nullable` instead of `Ptr` for value types that need null semantics ### Design Philosophy The object model enforces clear distinctions between: - Value types (lightweight, copyable) vs Reference types (heavyweight, shared) - Concrete classes vs Interfaces - Automatic memory management vs Manual lifetime control This design promotes: - Clear ownership semantics - Reduced memory leaks - Type safety - Polymorphic behavior through interfaces