Jump to content
  • Advertisement
Sign in to follow this  
noodleBowl

Void Pointers as variables?

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

I was wondering about this:
 
I have this class called ApplicationWindow
class ApplicationWindow
{
public:
	ApplicationWindow();
	virtual ~ApplicationWindow();
	void *GetWindow();
	int32_t GetWidth();
	int32_t GetHeight();

protected:
	void *windowHandle;
	int32_t width;
	int32_t height;
};
And I also have this class EGLDisplayWindow which will inherit ApplicationWindow
class EGLDisplayWindow : public ApplicationWindow
{
public:
	EGLDisplayWindow();
	~EGLDisplayWindow();
	void CreateWindow(void *windowHandle);

private:
	void CreateAndroidWindow();
	void CreateIOSWindow();
	void DestroyWindow();


};

As you can see ApplicationWindow has a private variable called windowHandle and a method called GetWindow()
When a EGLDisplayWindow is created my idea is to create the proper window needed by each application. Then store that "window" into the windowHandle variable, where it can be accessed using the GetWindow() method

Is this a bad idea (including the void pointer part)? Is there a better solution? Edited by noodleBowl

Share this post


Link to post
Share on other sites
Advertisement

The android/ios names suggest to me that this is for different window types on different platforms? Presumably you need to build different binaries for different platforms, so why not use #ifdef directives to control this instead (I mean... how would you implement CreateIOSWindow on android anyway?)

Edited by phil_t

Share this post


Link to post
Share on other sites

The android/ios names suggest to me that this is for different window types on different platforms? Presumably you need to build different binaries for different platforms, so why not use #ifdef directives to control this instead (I mean... how would you implement CreateIOSWindow on android anyway?)

Yeah, inheritance is the wrong mechanism here.

Depending on the complexity, you could also just have different cpp files for each platform. So you'd end up with
- ApplicationWindow.h // define platform neutral interface
- ApplicationWindow_Common.cpp // shared implementation
- ApplicationWindow_IOS.cpp // iOS specific code
- ApplicationWindow_Android.cpp // android specific code
And so on. Then just build the files you need on each platform

Share this post


Link to post
Share on other sites

Is this a bad idea (including the void pointer part)? Is there a better solution?

Well, you're sort of on the right track (for example, on Linux, where you could have an X11 window, a Wayland window, a Mir window, all in the same binary).  That's the whole thing about native EGL windows, and the solution is either a void* or something aliased to a void*.

 

Your code above, however, is not using a void* but trying to instantiate a void.  That's not gonna work.

Edited by Bregma

Share this post


Link to post
Share on other sites

It's basically the same as the void pointer approach, but with a kind of comment forcible attached to all the opaque pointers


It also gives you compile-time type checks to make sure you aren't accidentally passing something that's not an InternalWindow to a function that wants an InternalWindow.

Even back in the OP's use case, using opaque pointers further means that you can't make mistake as easily. &foo automatically converts to void* but not to ArbitraryType*. Even if you want to pass in pointers to arbitrary types, you almost certainly want to require the user to do so very very explicitly, so using opaque (undefined) pointers in place of void* makes your interface harder to accidentally misuse, which is always good. At least use those kind of opaque pointers in the public interface (using void* in the internals is fine).

Share this post


Link to post
Share on other sites

The android/ios names suggest to me that this is for different window types on different platforms? Presumably you need to build different binaries for different platforms, so why not use #ifdef directives to control this instead (I mean... how would you implement CreateIOSWindow on android anyway?)


Sorry I never fully explained this, but yes you are correct it is for creating different windows on different platforms.
Basically my idea was to call CreateWindow(void *windowHandle) and then the guts of this method would look like:
 
void EGLDisplayWindow::CreateWindow(void * windowHandle)
{
     this.windowHandle = windowHandle;

#if defined(_ANDROID_)
   
    CreateAndroidWindow(this.windowHandle);

#endif

//Other platforms that need EGL Windows

}

Your code above, however, is not using a void* but trying to instantiate a void.  That's not gonna work.


Yep! It was a typo. I fixed it up top
 
 

The protected keyword in C++ is ugly. It's usually a good hint there's a better design hiding somewhere. That's off topic though smile.png

 
Why is protected bad in C++? How else do you hide data members  from everyone and only expose them to the inherited classes?

Personally, I like to make my own opaque pointer types for better self-documentation.


To make an opaque pointer is it literally only a empty struct?

Share this post


Link to post
Share on other sites

To make an opaque pointer is it literally only a empty struct?

It's not even an empty struct - it's a struct that's only ever been forward-declared (so if you ever tried to actually create one, you'd get a conpuler error).

Why is protected bad in C++? How else do you hide data members  from everyone and only expose them to the inherited classes?

Generally, you don't - that's what's bad about protected.
It's not a black and white rule, but a soft guideline, or a "code smell".
Architectures based on implementation-inheritance (as opposed to interface-inheritance often break a lot of OO design priciples).

Share this post


Link to post
Share on other sites

Why is protected bad in C++? How else do you hide data members  from everyone and only expose them to the inherited classes?

 
Because data members should never be protected, and few functions should use it.  It does have some uses, but protected is rarely useful in C++, and most code can get away with never using it.
 
Herb Sutter (the chair of the C++ language committee basically for the past 20 years) has written several articles on it.  I've included some links to some of the writing, there are probably better write-ups.
 
Basically it looks like this:
 
 
 
PUBLIC:
* Interface functions should be public.  (The public functions should not be virtual. A surprisingly huge amount of bad code uses public virtual functions to achieve it's problems. When you can replace both the interface and behavior you can subvert things easily, both to be evil and as an accidental source of bugs.)
* Data members of POD classes/structs that serve as data bundles rather than logical classes.
* Base class destructor that is virtual and requires polymorphic destruction.
 
PROTECTED:
* Non-virtual utility functions to be used by child classes that relies on other member data in this base class. (Rare situation)
* Base class destructor that is non-virtual. (Rare situation)

* Virtual functions to be used by base classes that cannot be private because base classes must call them explicitly. (Design smell and source of bugs. Virtual functions are customizations that are an implementation detail. Why do you need to explicitly call a parent's customization? How do you know that customization will never change? If you have a tendency to do this, will you retrofit all other classes when it becomes necessary for others to use it? Instead put that into a protected utility function so all descendants can use it. )

 
PRIVATE:
All data members, unless this is a data-only bundle.
* Any function not part of the publicly visible interface.  This includes utility functions and virtual functions.

 

The vast majority of all code belongs in the public and private arena.  There are occasional uses of protected, but they are rarely encountered.

Edited by frob
formatting.

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!