   class interfaces
  I have a class CGraphics that I want to be completely API-independent, because it will manipulate other classes such as CD3DGraphics to perform the actual work. The problem is, I'm not sure how I should have the classes depend on each other. I've come up with a couple solutions, but none of them satisfy me very well:   class CGraphics {};class CD3DGraphics : public CGraphics {};// use base class pointer to remove API-dependenceCGraphics* pGraphics = new CD3DGraphics;The problem with the above is that the client code still needs to know about the specialized class, while I'd like the CGraphics class to stand alone and handle the CD3DGraphics class by itself. WIth this in mind:   // class has pointer to base class so it can store derived classesclass CGraphics {public:    HRESULT Initialize();private:    CGraphics* m_pRenderer;};// derived classclass CD3DGraphics : public CGraphics;// instantiate appropriate derived class, and initialize itHRESULT CGraphics::Initialize() {    m_pRenderer = new CD3DGraphics;    return m_pRenderer->Initialize();}This works as well, but for some reason it unsettles me to have to explicitly call CD3DGraphics::Initialize() in the base class. Also, what if I have another class that CGraphics doesn't know about, like CUnknownGraphics? How would I create that then? I need to have a solution that's not hardcoded, so I can load the code from a DLL. Last solution, class hell:   // basic class that CD3DGraphics derives fromclass CBaseGraphics;// graphics class interface, the only part visible to the clientclass IGraphics {public:    HRESULT Initialize( CBaseGraphics* );private:    CBaseGraphics* m_pRenderer;};class CD3DGraphics : public CBaseGraphics {};HRESULT IGraphics::Initialize( CBaseGraphics* pImpl ) {    m_pRenderer = pImpl;}I like my code to be concise, so having this many classes disturbs me even more than my second example. That's basically the only complaint I can find with this model.Which of these do you think would work best for me? Is there another that I haven't thought of? It's nothing serious, but ugly code seriously disturbs me, and I want to make sure I have the right classes.edit: topic title didn't make much sense. and damn forum html.[edited by - psykr on November 13, 2003 2:23:28 PM]
  First, IGraphics is not an interface. An interface should only declare functions and can''t have any members. If I understand you right, you will only have one subtype of CGraphics available to the client code, but you want to hide it and be able to change it at runtime(?).One idea would be to make a simple factory, where you register a pointer to a function that can create the chosen concrete graphics class. If the user wishes to use OpenGl, you simply register a function that creates a COpenGlGraphics object. The client code uses the factory, not knowing the concrete type of CGraphics. CGraphics should have a protected constructor, forcing the client code to use the factory: struct CGraphics{public:    virtual void f() = 0;protected:    CGraphics() {}};struct CD3DGraphics : public CGraphics{    virtual void f() {}};struct COpenGlGraphics : public CGraphics{    virtual void f() {}};// creators, well hidden from clientCGraphics* CreateD3DGraphics(){    return new CD3DGraphics();}CGraphics* CreateOpenGlGraphics(){    return new COpenGlGraphics();}// factoryclass GraphicsFactory{    typedef CGraphics* (*GraphicsCreator)();public:    static GraphicsFactory& Instance()    {   static GraphicsFactory instance;   return instance;    }    void setGraphicsCreator(GraphicsCreator gc)    {   gc_ = gc;    }    CGraphics* create()    {   if ( 0 == gc_ )   {  throw std::runtime_error("no graphics available");   }   return (gc_)();    }private:    GraphicsCreator gc_;    GraphicsFactory() : gc_(0)    {    }    ~GraphicsFactory()    {    }    GraphicsFactory& operator=(const GraphicsFactory&);};int main(){    CGraphics* cg = 0;   // manager registers D3D graphics    GraphicsFactory::Instance().setGraphicsCreator(CreateD3DGraphics);   // client    cg = GraphicsFactory::Instance().create();    cg->f();    delete cg;    // manager registers OpenGl graphics    GraphicsFactory::Instance().setGraphicsCreator(CreateOpenGlGraphics);    // client    cg = GraphicsFactory::Instance().create();    cg->f();    delete cg;}Well, that''s one alternative. I hope the code didn''t disturb you ;  When my engine boots up one of the first things it does it looks into a config file to find the plugin directories. It then scans these directories for dll''s to load. All my plugin dll''s have a startPlugin and stopPlugin C Function. So when the engine loads it it calls startPlugin().Now a DirectX 3D renderer dll would, in its startPlugin would first instantiate the D3DDriver and then register this pointer with the engine via a registerRenderDriver(pointer) type function. (The engine is a singleton)Now the registerRenderDriver function in the engine takes a IDriver* as a parameter and the D3DDriver is of course a IDriver too.So this way the engine has no idea what type of render drivers it has just a list of IDriver*. 