0

I'm having trouble figuring out what to return to the user of my Manager class in order to express the fact that I own the resource (in my example a Window). I want to pass to the client an interface IWindow exposing only a limited set of methods from the actual Window implementation. What should I return a reference or a pointer? Better Manager class implementation?

class IWindow
{
public:
    virtual ~IWindow(){}
    virtual void setMember() = 0;
protected:
    IWindow(){}
};

class Window : public IWindow
{
public:
    Window(){}
    virtual ~Window(){test_ = 0;}
    virtual void setMember() final { test_++; }
private:
    int test_ = 11;
};

class Manager
{
public:
    Manager():window_{ std::make_unique<Window>() } {}
    virtual ~Manager(){}
    // ownership not obvious
    IWindow* getWindowPtr() const { return window_.get(); }
    // ownership clear but is this the right thing to do?
    IWindow& getWindowRef() const { return *window_.get(); }
private:
    std::unique_ptr<IWindow> window_ = nullptr;
};

int main(void)
{
    Manager manager; // Owner of the window.

    IWindow* iWindowPtr = manager.getWindowPtr(); // Client get's an interface pointer.
    iWindowPtr->setMember(); // Call some method (only interface methods visible).
    // Basically now he could delete the pointer and crash the Manager he has no idea that Manager owns this pointer
    // delete iWindow;
    // Crash when manager goes out of scope!

    IWindow& iWindowRef = manager.getWindowRef(); // Client get's an interface ref.
    iWindowRef.setMember(); // Call some method (only interface methods visible).
    // Now client knows that he does not have ownership, but I'm returning a ref from a raw pointer...

    return 0;
}
CrHasher
  • 343
  • 3
  • 11
  • Related: http://stackoverflow.com/q/23112178/420683 – dyp Apr 17 '14 at 14:37
  • What's the idea of that `Manager` class? If it shall hide the implementation of `IWindow`, you can use the PIMPL idiom instead (i.e. don't return a pointer to some polymorphic type, but wrap the polymorphism in a non-polymorphic class). – dyp Apr 17 '14 at 14:42
  • The **Manager** is already using **PIMPL** (hiding private implementation with an **opaque pointer**). The issue here is giving some limited control to the user through an **interface** but at the same time I want to be explicit about **ownership**, meaning the user should know I’m the owner of the window. I could make **Window** PIMPL too and then it would become a non polymorphic type and returning a ref to it would be the obvious correct thing to do, but then **Manager** class can’t explicitly control the lifetime of the window_ member. Is it wrong to return polymorphic types from classes? – CrHasher Apr 18 '14 at 08:22
  • What I wanted to point out is that your `Manager` class does not do much more than some factory function which returns a `unique_ptr`: It provides a managed (smart) pointer to the implementation. You can instead use some class `Window` which has a non-virtual interface (calling the implementations' virtual functions). Proper resource management IMHO includes providing an interface to the resource, not just acquiring and releasing it. – dyp Apr 18 '14 at 12:11

1 Answers1

0

I am seeing new Window{} which is not right, it should be new Window().

Now i suggest you use more advanced options

{ std::make_unique<Window>(); }

Edit: For the first part it appears i was wrong new Window{} is a correct sintax

ciprianr
  • 191
  • 1
  • 1
  • 15
  • 2
    *"which is not right"* Why shouldn't it be right? It's uniform initialization syntax, and does the same thing as `()` here. `make_unique` is C++1y, but it's a good idea to use it anyway (provide your own implementation if your Standard Library implementation doesn't contain one). – dyp Apr 17 '14 at 14:36
  • I implemented make_unique but had a lot of problems with it so I decided for now I won't use make_unique in this example. I'm still searching for a make_unique implementation that actually works ;) – CrHasher Apr 18 '14 at 08:29
  • Just found: Stephan T. Lavavej's implementation of unique_ptr that works correctly so I just added it to my code base :D – CrHasher Apr 18 '14 at 08:42