Jump to content


Check out our Community Blogs

Register and join over 40,000 other developers!


Recent Status Updates

View All Updates

Photo
- - - - -

Multiple Interface Inheritance

inheritance

  • Please log in to reply
1 reply to this topic

#1 Buttacup

Buttacup

    CC Resident

  • Just Joined
  • PipPipPipPip
  • 71 posts

Posted 03 January 2010 - 10:07 AM

I'm having a hard time wrapping my brain around this....

I have 3 Interfaces:

class CTool
{
public:
     virtual UI_TOOL GetUI_T_ID() = 0;
     virtual HRESULT Activate() = 0;
     virtual HRESULT Execute(SMouseStroke*) = 0;
     virtual HRESULT Park() = 0;

     virtual void SetToolDeactivate(bool) = 0;
     virtual bool isToolDeactivate() = 0;

private:
     CTool& operator=(const CTool&);
};

class CEntity
{
public:
     CEntity(){}

     virtual ENTITY GetEntityID() = 0;

     virtual bool isActive() = 0;
     virtual void SetActive(bool) = 0;

     virtual void SetWorldMatrix(D3DXMATRIX) = 0;
     virtual D3DXMATRIX GetWorldMatrix() = 0;

private:
     CEntity& operator=(const CEntity&);

};

class CEntity3D
{
public:
     CEntity3D(){}

     virtual void SetObjectFile(string) = 0;

     virtual void GetObject() = 0;
     virtual vector<SBasicModel>* GetModel() = 0;

     virtual void SetVisible(bool) = 0;
     virtual bool isVisible() = 0;

     virtual void SetScenePurged(bool) = 0;
     virtual bool isScenePurged() = 0;

private:
     CEntity3D& operator=(const CEntity3D&);

};


and I have one object I wish to implement all three:


class CToolMoveGeometry : public CTool, public CEntity, public CEntity3D
{
private:
     UI_TOOL UI_T_ID;

     void SetLBDownPrior(){lb_down_prior ? lb_down_prior = false : lb_down_prior = true;};
     bool GetLBDownPrior(){return lb_down_prior;};

     void SetRBDownPrior(){rb_down_prior ? rb_down_prior = false : rb_down_prior = true;};
     bool GetRBDownPrior(){return rb_down_prior;};

     static bool lb_down_prior;
     static bool rb_down_prior;

public:
     CToolMoveGeometry() : UI_T_ID(TOOL_MOVE_GEOMETRY)
     {
          id = E_UI_TOOL;

          E_Name = "UIToolMoveGeometry";
          object_file = "C:/Projects/Naomies Moon/Assets/TranslationXY.NMM"; 

          is_active = true;
          is_visible = true;
          is_scene_purged = false;

          D3DXMatrixIdentity(&E_World);

          GetObject();
          E_Body = E_Object.GetPtrBasicModel();
          is_d3d_buffered = true;
     }

     virtual UI_TOOL GetUI_T_ID(){return UI_T_ID;};
     virtual HRESULT Activate();
     virtual HRESULT Execute(SMouseStroke*);
     virtual HRESULT Park();

     deque<SDrawCommand> vDrawCommands;

     vector<SEditModel>* vClay;

private:
     virtual void SetToolDeactivate(bool set){tool_deactivate = set;};
     virtual bool isToolDeactivate(){return tool_deactivate;};
     bool tool_deactivate;

private:
     StateOfBeing MGT_State_Report;
     CStateReport* MGT_Report;
     CMsg_Box* MGT_Msgs;

private:
     ENTITY id;

public:
     virtual ENTITY GetEntityID(){return id;};

     virtual bool isActive(){return is_active;};
     virtual void SetActive(bool activate){is_active = activate;};

     virtual void SetWorldMatrix(D3DXMATRIX world){E_World = world;};
     virtual D3DXMATRIX GetWorldMatrix(){return E_World;};

     virtual void SetObjectFile(string file){object_file = file;};

     virtual void GetObject(){E_Object.Instatiate(object_file);};
     virtual vector<SBasicModel>* GetModel(){return E_Body;};
     virtual bool isD3DBuffered(){return is_d3d_buffered;};

     virtual void SetVisible(bool visible){is_visible = visible;};
     virtual bool isVisible(){return is_visible;};

     virtual void SetScenePurged(bool purge){is_scene_purged = purge;};
     virtual bool isScenePurged(){return is_scene_purged;};

private:
     string E_Name;

     bool is_active;
     bool is_visible;
     bool is_scene_purged;

     D3DXMATRIX E_World;

     C3DLocker E_Object;
     string object_file;
     vector<SBasicModel>* E_Body;
     bool is_d3d_buffered;
};


Now when I was using one I saw the beauty in this as being I could have a great way of indexing through a bunch of tools that had to have the same method signatures with different implementation... yay!

But with three I store as CTool* and cast to CEntity3D* and it's like *cough* can't do that?????

[me] shakes fist [/me]

eg:
     CToolMoveGeometry* ptr = reinterpret_cast<CToolMoveGeometry*>(UI.DevTool.GetActiveTool());
     CToolMoveGeometry tool = *ptr;
     CEntity3D* ptr2 = reinterpret_cast<CEntity3D*>(&tool);
     vector<SBasicModel>* model = ptr2->GetModel();
     vWorld = *(ptr->GetModel());

note that I even dereferenced to implementing class and then rereferenced it as CEntity3D!

This still works great though:
     CToolMoveGeometry* ptr = reinterpret_cast<CToolMoveGeometry*>(UI.DevTool.GetActiveTool());
     vWorld = *(ptr->GetModel());

Seems now like I'm just writing extra code???
  • 0

#2 Buttacup

Buttacup

    CC Resident

  • Just Joined
  • PipPipPipPip
  • 71 posts

Posted 03 January 2010 - 11:26 AM

Solution:

    CEntity3D* ptr = dynamic_cast<CEntity3D*>(UI.DevTool.GetActiveTool());
    vWorld = *(ptr->GetModel());

Apparently Up, Down and Cross casting have different needs yus??? :P

link

In the terminology of casting we are using following expressions

* Up cast: We receive the interface IInterfaceA and want the interface IZUnknown. So we're going one step up in our class hierarchy. The C++ compiler will do this automatically without any cast operations (implicit cast).
* Down cast: We receive the interface IZUnknown and want the interface IInterfaceA. So we're going one step down in our class hierarchy. This cast is problematic for the C++ compiler. It's done with the type informations at runtime, simply to check if the cast is valid (see dynamic cast).
* Cross cast: We receive the interface IInterfaceA and want the interface IInterfaceB. We traverse across the hierarchy. Like the down cast, the C++ Compiler can't check this. It's done with type informations at run time.

C++ knows 4 kind of castings and includes the C cast using brackets.

* Reinterpret cast: IA* pObj = reinpterpret_cast<IA*>(pObject);
* Static cast: IA* pObj = static_cast<IA*>(pObject);
* Const cast: IA* pObj = const_cast<IA*>(pObject);
* Dynamic cast: IA* pObj = dynamic_cast<IA*>(pObject);

The reinterpret cast casts a pointer explicit to an other pointer type, checking only the sizes of the pointers to convert (function to object casts and inverse). This cast is not useful for our interface casting, because it does not care about multi inheritance, witch we need since we have no implements-keyword like Java does.

The static cast is similar to the C-cast using brackets. But static cast can not really down cast. The down cast works only for single inheritance. And therefore the cross cast does not work at all. So we can not use the static cast for our interface casting.

The const cast is only used to cast the const qualifier away.

At the end we have a look at the dynamic cast. The dynamic cast is able to down and cross cast, because it uses the type information of the classes. The cast is done at runtime, an it takes more process time than any other cast. I've found out that there are still two problems using dynamic cast.


  • 0





Also tagged with one or more of these keywords: inheritance