• Advertisement
Sign in to follow this  

Protection of methods from the implementer's inheritors

This topic is 703 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi there,

 

for my first go at a game engine, i implemented the engine into a framework class (D3DApp) and inherit from that to only modify the initialize / update and draw methods (Engine::public D3DApp).

 

Now in my D3DApp framework class, i create an object of another class, e.g. the "SoundManager". That class has e.g. an "initialize" method that should be called in the D3DApp's initialize method and a "LoadSound()" method that should be available to the Engine class. But i don't want the "administrative" methods of the "SoundManager"-class to be available to the inherited framework.

 

How do i do that?
I mean i could just make the soundmanager class in the D3DApp private and provide public methods in the framework that themselves call the "LoadSound()" method of the soundmanager. But that would mean that, if I for example change that method's return type, i would have to update one more method definition and one method call.

Is there any way to hide functions of an object from those objects that inherit from the class implementing the first object but not from the class implementing it?

 

Thanks in advance for any help. Oh and if the solution is obvious, I am a beginner!

Share this post


Link to post
Share on other sites
Advertisement
Quick answer: Don't use implementation inheritance for frameworks.
These kinds of frameworks often look like this:
struct Framework
{
  void SomethingConcrete()
  {
    SomethingElseConcrete();
    SomeUserBehaviour();
  }
 
  virtual void SomeUserBehaviour() = 0;
}
You should instead use interfaces:
struct UserExtension
{
  virtual void SomeUserBehaviour() = 0;
}

struct Framework
{
  UserExtension* user;
  void SomethingConcrete()
  {
    SomethingElseConcrete();
    user->SomeUserBehaviour();
  }
}
Or function-objects:
struct UserExtension
{
  std::function<void()> someUserBehaviour;
}

struct Framework
{
  UserExtension* user;
  void SomethingConcrete()
  {
    SomethingElseConcrete();
    user->someUserBehaviour();
  }
}

Now in my D3DApp framework class, i create an object of another class, e.g. the "SoundManager". That class has e.g. an "initialize" method that should be called in the D3DApp's initialize method and a "LoadSound()" method that should be available to the Engine class. But i don't want the "administrative" methods of the "SoundManager"-class to be available to the inherited framework.

Also, Initialize functions usually shouldn't exist, but should be done by the constructor - that's what they're for.
But - using that example with interfaces, you can have an alternative "view" of the SoundManager object, such as an ISoundLoader interface.
struct ISoundLoader
{
  virtual Sound* LoadSound() = 0;
};
struct SoundManager : ISoundLoader 
{
  void Init();
  Sound* LoadSound();
};

struct Game
{
  virtual void Update( ISoundLoader& sounds )
  {
    Sound* s = sounds.Load();

    sounds.Init();//compile error - this interface only grants access to the Load function
  }
}

class D3DApp
{
  SoundManager sounds;
  Game game;
  D3DApp()
  {
    sounds.Init();
  }
  void Update()
  {
    game.Update( sounds );
  }
}
Edited by Hodgman

Share this post


Link to post
Share on other sites

I tried to fit what I did into one of the methods you described - and am not sure where exactly I would land.

What I do is this:

 

This is the framework:

class D3DApp
{
public:
   D3DApp();

   virtual bool Initialize();
   virtual bool Update() = 0;

private:
  bool InitializeD3D();

public:
  SoundManager mSoundManager;
};

bool D3DApp::Initialize()
{
  InitializeD3D();
  mSoundManager.Initialize();
  return true;
}

bool D3DApp::InitializeD3D()
{
   //D3D Stuff
}

These sound objects are to be used to "store" all the sounds at runtime:

struct Sound
{
    //some sound properties, buffer, name, type, etc
}

The Soundmanager should provide functions that create sound objects and add them to the sound buffer

class SoundManager
{
public:
          SoundManager();

          bool Initialize();
          bool CreateSound(char* filename, char* SoundName, Sound& sound);
          bool AddSountToStream(Sound sound);

private:
          Sound sounds[32];
};

The Game Class inherits from the framework - this is where sounds should be added and where should be decided, when to play them

class Game : public D3DApp
{
public:
    public Game();

    bool Initialize();
    bool Update();

private:
    SoundClass mSomeSound
};

Game::Game()
{
}

bool Game::Initialize()
{
   D3DApp::Initialize();

   mSoundManager.Initialize() // i dont want this to work!
   
   mSoundManager.CreateSound("/file.wav", "Soundname", mSomeSound) // i want this to work!

   //other initialization stuff
}

bool Game::Update()
{ 
 // own update logic, at some point this: 
  mSoundManager.AddSoundToStream(mSomeSound); //i want this to work!
}

Apart from being uncomplete, of course, how bad is that? :S

I did not want to implement the SoundManager in the Game class directly, as the functions that it provides, should be available to any class that inherits from the framework.

Edited by Moongoose

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement