Jump to content
  • Advertisement
Sign in to follow this  
ill

Interfaces in C++?

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

C++ bugs me in that it ends up exposing functionality to different parts of the program that shouldn't have it. It's also really annoying when I end up putting header files in some class's header that I can't forward declare and the code that includes the class ends up including headers it shouldn't.

An example would be my texture class has a private GLUint storing the texture and I have to #include openGL headers to have a GLUint variable. This makes my in game object also include OpenGL headers just to have a texture object and be able to do OpenGL calls when it shouldn't. I get around this by storing the texture as unsigned int and not a GLUint and only including OpenGL headers in the texture's cpp file but that's just an example of some of the annoying things of C++.

Another example is the low level game engine code that needs to be able to instantiate the main classes and update them. Then there's the high level game engine code so an in game object can play a sound effect or tell the renderer that there is a triangle to be drawn.

At the moment I tried doing that by having low level stuff be private and high level stuff be public. Then the low level stuff are all friend classes of each other. It's becoming a mess.

I like how it works in Java but the only way I can think of doing it with C++ is with a bunch of virtual functions to call methods that originally don't have to be virtual. This also makes it hard to have inline methods which are nice when I'm just trying to make a getter method.

Does the compiler know how to optimize out virtual functions and make them nonvirtual by not having to go through the vtable? I can see how it would if I have a virtual method call that can only ever be one specific class's virtual method but is that actually possible?

Share this post


Link to post
Share on other sites
Advertisement
C++ allows you to do the following, which is probably cheaper than Java interfaces.

class LowLevelClass
{
public:
void frobnicateFoo();
void frobnicateBar();
const FooBar &getFooBar() const;
private:
// ...
};

class FooInterface
{
public:
FooInterface(LowLevelClass *inner) : inner(inner) {}

void frobnicate() { inner->frobnicateFoo() };
private:
LowLevelClass *inner;
};

class BarInterface
{
public:
BarInterface(LowLevelClass *inner) : inner(inner) {}

void frobnicate() { inner->frobnicateBar() };
private:
LowLevelClass *inner;
};

class FooBarStatus
{
public:
FooBarStatus(LowLevelClass *inner) : inner(inner) {}

const FooBar &status() const { return inner->getFooBar() };
private:
LowLevelClass *inner;
};

The higher levels of your application never get a direct reference to the LowLevelClass. However, the "Interface" classes here will be compiled away. They are boilerplate heavy though. The key point here is that the "interfaces" are actually concrete, value objects. Its a little weird, but it works. I've completely ignored ownership issues here, you might want to store smart pointers instead.

Share this post


Link to post
Share on other sites
Look into PIMPL idiom. Basically, you can have an opaque pointer to a privately defined type (that you forward-declare in the header) that contains all of the implementation-specific data for a particular class. I use it everywhere in my graphics library that I need to store things like GLuints, etc. without having to have OpenGL headers exposed to the user.

Share this post


Link to post
Share on other sites
It's probably obvious, but you should note that this doesn't actually improve run time performance at all. It's just an ugly workaround for C++'s poor compilation model.

You're almost always better off using a C abstract type (no performance hit and no boilerplate), unless the base class has a lot of functionality you need to use (in which case it's not really an interface).

Share this post


Link to post
Share on other sites

An example would be my texture class has a private GLUint storing the texture and I have to #include openGL headers to have a GLUint variable. This makes my in game object also include OpenGL headers just to have a texture object and be able to do OpenGL calls when it shouldn't. I get around this by storing the texture as unsigned int and not a GLUint and only including OpenGL headers in the texture's cpp file but that's just an example of some of the annoying things of C++.
GLuint is, spoiler alert, always "unsigned int". You can use the GL* datatypes if you like, but they are primarily there for cross-language compatibility, and of no significance to C/C++ developers. (In particular, they do NOT help with cross-platform compatibility.)

Another example is the low level game engine code that needs to be able to instantiate the main classes and update them. Then there's the high level game engine code so an in game object can play a sound effect or tell the renderer that there is a triangle to be drawn.[/quote]I'm not sure why your high level game engine codes would be telling your renderer about triangles, but yeah... deciding where the interface line between "game level" and "execution engine" is, is always difficult.

The private/public line is easier to draw. If you're willing to maintain it as part of the class interface, and make sure that it respects class invariants, and you need it from outside the class, it's public. Otherwise, it's private.

C++ has no notion of "package protection", unlike Java, and as you've seen, #includes (in particular, indirect #includes) are not always perfect predictors of what a particular block of code does and does not have any business messing with. The language is not going to help you very much in this respect. One tool that can be useful is namespaces -- but as an organizational tool, not as a compile-time check.

Does the compiler know how to optimize out virtual functions and make them nonvirtual by not having to go through the vtable? I can see how it would if I have a virtual method call that can only ever be one specific class's virtual method but is that actually possible?
[/quote]It's funny that people don't worry about function call overhead in languages where you can't avoid it, but pinch pennies when it's laid bare in languages like C++. I find myself doing it too. Executing tens of millions of virtual function calls per frame will definitely show up on your profiler. Below that threshold, don't worry about it. (The threshold is different on consoles.)

Share this post


Link to post
Share on other sites
Note that just because it includes all OpenGL header indirectly doesn't mean that it is increasing size. It just means that it knows about the symbols now. It doesn't get compiled into the compilation unit, at least as far as I know.

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.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!