Jump to content
  • Advertisement
Sign in to follow this  
Mufflot

Hiding interfaces from the user. C++

This topic is 2784 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

In my current project I don't want a user to be able to create an object, which is handled internally by some other class. F.ex. if I have this Time class, which is created when the engine is created, I want to hide the constructor. My current code is like this:


class Time
{
public:
float GetDeltaTime();
...

private:
Time();
...

friend class Engine;
}



By going with this method, I declare friendships everywhere. I'm wondering, can this be done in some way without friendships?

Mufflot

Share this post


Link to post
Share on other sites
Advertisement
You can hide/prevent the object creation/deleting from user for example by creating interface for your Time class like this:


// Time interface.
class Time
{
protected:
// protected destructor prevents the user from deleting your time object.
virtual ~Time()
{
}
public:
virtual float GetDeltaTime() = 0;
};

// Engine interface.
class Engine
{
public:
virtual ~Engine()
{
}

virtual Time* GetTime() = 0;
};




In somewhere you have implemented the Time and Engine interfaces like this:


// Class which implements the time interface.
class TimeImplementation: public Time
{
public:
TimeImplementation()
{
}

virtual ~TimeImplementation()
{
}

virtual float GetDeltaTime()
{
// TODO: Implement!
return 1.0f;
}
};

// Class which implements the engine interface.
class EngineImplementation: public Engine
{
public:
EngineImplementation()
{
}

virtual ~EngineImplementation()
{
}

virtual Time* GetTime()
{
return &iTime;
}
private:
TimeImplementation iTime;
};

// Function which creates the engine.
Engine* CreateEngine()
{
return new EngineImplementation;
}



Here is an example code for creating and using the engine.


void example()
{
Engine* engine = CreateEngine();

Time* time = engine->GetTime();
float deltaTime = time->GetDeltaTime();

delete engine;
}



Share this post


Link to post
Share on other sites
There is the pimpl-idiom, where the implementation is only visible to internal places, and the interface would have a pointer to that forward declared implementation. This could help you emulate .net's internal visibility.

[nitpick: your class declaration is missing a semicolon]

edit: s/impl/pimpl/

Share this post


Link to post
Share on other sites
I would just put the headers in a directory called "internal" or "private" or something like that. It communicates clearly that the classes should not be used outside the API and it doesn't clutter the code.

Share this post


Link to post
Share on other sites
Quote:
Original post by Mufflot
Thanks for the replies!

I'm going to try out ttstreamer's solution, it looked quite nice.


So how do you prevent users from creating an instance of TimeImplementation?

Share this post


Link to post
Share on other sites
jonathanjansson: Haha yeah I actually missed the part where XImplementation's constructor was public ;).

SiCrane: Sounds like a good idea, any tips on how can you do that? I'm not at my home so I can't really try it out by myself atm.

Share this post


Link to post
Share on other sites
Quote:
Original post by Mufflot
SiCrane: Sounds like a good idea, any tips on how can you do that? I'm not at my home so I can't really try it out by myself atm.


The post right in the middle between your "I'm wondering" and "Thanks for the replies!" contains a clue, as does this post.

pimpl

Share this post


Link to post
Share on other sites
The first question you should ask yourself when trying to hide something from the user isn't how, but why. Is there any good reason your user shouldn't be able to create their own Time instances? And by "good reason" I mean will it break your engine in any way if a second one is created, or are you just doing this out of a sense of "you should only need one of these."

If it won't break your engine to create a second Time instance*, then don't bother hiding it from the user. They can access your engine's instance if they want to, or maybe they'll think of something you haven't and will want to make a second one for some reason. Generally speaking, the only good reason to hide something from the user is if it has the potential to break things and you need to limit access in a way that avoids that potential**.

-----
* In such a circumstance you should be using a singleton design anyway, or even better, changing the design so that this won't be an issue.

** Good example: for classes that expect to be managed by a shared_ptr or intrusive_ptr or such, you might decide to use a private constructor with the named constructor idiom which creates them inside the appropriate smart pointer so the user can't forget to put them in one.

Share this post


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

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!