views:

81

answers:

5

I have a System class that can return a pointer to an Editor class. The Editor class is instantiated within the System class and passed pointers to System's private variables. The Editor class essentially acts as an alternative interface to System's internal data structures.

My question: Does a design pattern exist that allows me to prohibit the direct instantiation of the Editor class but somehow still instantiate it inside System?

Thanks.

+1  A: 

You can create an abstract interface for your Editor, and nest the implementation inside the definition of System. It can even be protected or private.

class IEditor
{
public:
   virtual int Whatever() = 0;  
};

class System
{
public:
  int foo;
  IEditor *GetEditor() { return &m_Editor; }

protected:
  class Editor 
  {
     virtual int Whatever() { return 1; }
     // etc...
  }

  Editor m_Editor;
}
Crashworks
+1 I am a fan of abstract interfaces; though the nested class could get messy.
joshperry
+6  A: 

You could make Editor's constructor private which would keep others from instantiating it and then making System a friend will allow it to access the constructor.

class System {
public:
    System() : editor_(new Editor()) { ... }

private:
    Editor* editor_;
}

class Editor {
    friend class System;
    Editor() { ... }
}
joshperry
This has the advantage of not making Editor's member functions indirect (virtual) which is a small (~7ns) CPU savings on each call.
Crashworks
Ah, this friend thing is exactly what I needed. New concept for me, thanks.
leo
@joshperry: In this approach, Editor is no longer an interface to the System class. It is no longer known to the outside world.!
Chubsdad
A: 

If you don't want to make nested classes, you could make class Editor a friend of System, and make the constructors and destructors of Editor private. That way only System is allowed to instantiate and destroy an instance of class Editor.

C Johnson
A: 

Consider making the copy constructor and the copy assignment private along with the constructor. The example below shows that editor1 and editor2 can be created if these two methods are not made private.

class Editor {  
private:  
    Editor();  
    friend class System;  
};  

class System {  
public:  
    Editor editor;  
};  

int main() {  
    System system;  
    Editor editor1(system.editor);  
    Editor editor2 = system.editor;  
    return 0;  
}  
skimobear
A: 

Why not split the System's state into another class? For example:

class SystemState {
};

class Editor {
    public:
        Editor(SystemState &state) :
            state(state) {
        }

    private:
        SystemState &state;
};

class System {
    public:
        System() :
            editor(new Editor(state)) {
        }

    private:
        SystemState state;

        Editor *editor;
};
strager