I'm planning out a design for my Window class. The goal is to provide an abstraction for creating a platform agnostic window ready for OpenGL rendering. I'm thinking of having a class 'Window' be the public interface, and a 'WindowImpl' class handle the work. Would making Window a friend of WindowImpl and calling WindowImpl functions inside Window cause issues? Technically, WindowImpl wouldn't be instantiated correct? So the destructor wouldn't be called which means the Window destructor wouldn't be called so a destroy function would be needed. Ex.
class MyWindow
{
public:
void create(width, height, title)
{
WindowImpl::create(width, height, title);
open = true;
}
void close()
{
WindowImpl::destroy();
open = false;
}
bool isOpen()
{
return open;
}
private:
bool open;
};
class WindowImpl
{
friend class MyWindow;
private:
static void create(width, height, title) {} // Creates the window
static void destroy()
{
XCloseDisplay(display);
}
static Display* display;
static Window window;
static GLXContext context;
};
I don't know if I'm going in the right way with this, or if I'm making things more complicated then they need to be. Since a different WindowImpl will be compiled depending on the target platform, I want to keep as much of it away from the user as possible, keeping all data like the window title and resolution inside of the Window class and any changes that are necessary can be made without the WindowImpl keeping track of anything more then the implementation specific stuff.
If it really has to be platform-agnostic, then my suggestion is to use something like this:
class WindowImpl
{
public:
virtual void setOwner(Window* pOwner) = 0
virtual void create(width, height, title) = 0;
virtual void close() = 0;
};
class Window
{
public:
void create(width, height, title)
{
mImpl->create(width, height, title);
open = true;
}
void close()
{
open = false;
mImpl->destroy();
}
Window(std::unique_ptr<WindowImpl> pImpl)
: mImpl(pImpl)
{
}
private:
std::unique_ptr<WindowImpl> mImpl;
};
// Then off somewhere else...
class WindowImplX11 : public WindowImpl
{
public:
void setOwner(Window* pOwner) {
mOwner = pOwner;
}
void destroy() {
XCloseDisplay(display);
}
private:
// Pointer back to the owner just in case (e.g. event
// delivery); if weak_ptr worked with unique_ptr, that
// would be better.
Window* mOwner;
Display* display;
GLXContext context;
};
This is a light version of the Bridge pattern, which is commonly used when you have two incompatible object hierarchies which you need to link together. This is a degenerate case (since the "hierarchy" has only one class in it), but it's still a useful technique to think about. Probably the most famous example of this is Java AWT (however AWT calls it "Peer" rather than "Impl").
Exactly how you split the responsibilities between the front end and back end is, of course, something that you need to decide for yourself, and there will probably be some back-and-forth. You may, for example, decide that an OpenGL context is a sufficiently important concept that you need to expose it to clients. The same goes for things like vsync fences which aren't fully supported in the standard way yet. Yes, I'm looking at you, OS X.
The only catch is how you construct a Window and its Impl. The traditional way is to use an abstract factory:
class Toolkit
{
public:
std::unique_ptr<Window> createWindow() = 0;
};
// then elsewhere...
// Should have been in the library, only left out by oversight.
template<typename T, typename ...Args>
std::unique_ptr<T> make_unique( Args&& ...args )
{
return std::unique_ptr<T>( new T( std::forward<Args>(args)... ) );
}
class ToolkitX11 : public Toolkit
{
public:
std::unique_ptr<Window>
createWindow() {
return make_unique<Window>(make_unique<WindowImplX11>());
}
};
There are other ways which are a little more Modern.
Related
I have an object "World obj;" that has a normal interface of methods for it's typical funcitonality, but I want to have an additional interface of methods specifically for initializing that should only be visible when I specifically need them.
An example might be like this:
class World{
public:
void draw();
void update();
void normalStuff();
void addATree(); // this should not be ordinarily available or visible,
void addACar(); // calling this might break the object
void addAClown();// if it's not in a ready state for it
private:
int m_data;
};
Is there a way to relatively hide addATree(); etc in a way that makes sense? Ideally the mechanism for revealing those methods would also put the object into a ready state for them, or at least fault if it's not possible.
Different approaches would be possible:
Don't change the code, just change the spec
No need to change the code. Change the API specification and if the caller throws garbage in he gets garbage out.
Make the functions check if they are allowed
Always safe.
class World{
public:
...
void addAClown() {
if(not allowed)
throw error or crash or output error message or just return;
else {
do the work;
}
}
private:
int m_data;
};
Write a function that only exposes the Interface if allowed
You can't protect against someone getting the interface early and use it longer than allowed.
You could extract the interface functions into a separate class.
class WorldInterfaceToProtect {
public:
void addATree() = 0; // this should not be ordinarily available or visible,
void addACar() = 0; // calling this might break the object
void addAClown() = 0;// if it's not in a ready state for it
};
then the main class can protect these functions.
class World : protected WorldInterfaceToProtect {
public:
void draw();
void update();
void normalStuff();
protected:
void addATree(); // this should not be ordinarily available or visible,
void addACar(); // calling this might break the object
void addAClown();// if it's not in a ready state for it
private:
int m_data;
};
You then need to add a function that exposes the interface.
class World ... {
public:
WorldInterfaceToProtect *GetInterface() { return allowed_cond ? this : nullptr; }
...
}
Separate the class itself and the builder
This only helps if the functions to be called are only allowed during construction and not later. Depending on the design of the builder you can get a good protection.
class World{
friend class WorldBuilder;
public:
void draw();
void update();
void normalStuff();
protected:
void addATree(); // this should not be ordinarily available or visible,
void addACar(); // calling this might break the object
void addAClown();// if it's not in a ready state for it
private:
int m_data;
};
class WorldBuilder {
static World *Build(...);
}
Perhaps split the world into more composable parts:
struct WorldInterface
{
virtual void draw() = 0;
virtual void update() = 0;
virtual void normalStuff() = 0;
};
class World : public WorldInterface
{
public:
void draw() override { /* actual drawing here */};
void update() override {};
void normalStuff() override {};
private:
int m_data;
};
class TreeWorld : public WorldInterface
{
public:
// takes a reference to the actual world engine and defers work to
// that
TreeWorld(World& worldEngine) : worldEngine_(worldEngine) {}
void draw() override { worldEngine_.get().draw(); };
void update() override { worldEngine_.get().update(); };
void normalStuff() override { worldEngine_.get().normalStuff(); };
void addATree() {
//do tree/world interaction here
}
private:
std::reference_wrapper<World> worldEngine_;
};
class CarWorld : public WorldInterface
{
public:
// takes a reference to the actual world engine and defers work to
// that
CarWorld(World& worldEngine) : worldEngine_(worldEngine) {}
void draw() override { worldEngine_.get().draw(); };
void update() override { worldEngine_.get().update(); };
void normalStuff() override { worldEngine_.get().normalStuff(); };
void addACar() {
//do car/world interaction here
}
private:
std::reference_wrapper<World> worldEngine_;
};
extern void play_tree_game(TreeWorld world);
extern void play_car_game(CarWorld world);
int main()
{
World worldEngine;
// initialise engine here
// play tree-phase of game
play_tree_game(TreeWorld(worldEngine));
// play car phase of game
play_car_game(CarWorld(worldEngine));
}
Good answers all around, I'll just add this because it was missing(?)
class World{
public:
void draw();
void update();
void normalStuff();
private:
int m_data;
};
class BuildableWorld : public World
{
public:
void addATree();
void addACar();
void addAClown();
};
Use the BuildableWorld at initialization phase and then just give a pointer to the base class type for others to use.
Sure, you need some way to give the "built" data for the base class to access, but that was not the issue here, right?
an alternative approach that has not been mentioned so far, may be to let addX() functions take parameters whose existence implies that World is in a valid state. Say, if you cannot add trees to a world without water, let World return an (optional) water object to pass to addTree ... in other words, you need to properly formalize World invariants:
class World{
public:
void normalStuff();
auto getAvaliableWaterBuckets() -> optional<WaterBuckets>;
auto getAvaliableSoil() -> optional<SoilPack>;
//...
void addATree( WaterBuckets&&, SoilPack&& );
//...
};
// in the meanwhile, in user land:
if( auto water = world->getAvaliableWaterBuckets() )
if( auto soil = world->getAvaliableSoil() )
world->addTree( std::move(*water), std::move(*soil) );
else
world->recycleWater( std::move(*water) );
the benefit of this approach is that the user is not forced to think about world state validity ( an error prone task ), he just thinks about what he needs in order to add a tree ( simpler, hard to use incorrectly ). Moreover, this scales well because addX() functions can share different objects ( addFlowers needs water, ... ) enabling the correct management of a possibly complex internal world state.
Of course, IMHO, if you need to use addX() strictly on world construction only ( and you don't plan to add trees later ), then the factory approach already mentioned in the comments seems the way to go ...
I've recently started unit testing my code, using Catch and Fakeit.
I have a wrapper class around the WinAPIs HWND.
class Window
{
public:
Window(HWND hwnd);
virtual void resize(int width, int height);
...
private:
HWND m_hwnd;
};
This and the tests for it work fine. For the tests I'm creating some actual
windows using WinAPI's CreateWindow(...).
However, I've stumbled upon a problem and I'm not sure what's the best solution to it.
In my code I just kept passing Window by value, since it's basically just the HWND anyway.
Some methods take it as const&, but when using it as class members, I usually just copied it.
class Foo
{
public:
Foo(const Window& window)
: m_window(window)
{}
private:
Window m_window;
};
Now lets assume I want to test Foo. I need to somehow stub the Window class, but I can only do that
if I am able to override virtual methods. I think you see the problem here.
class Foo
{
public:
Foo(const std::shared_ptr<Window>& window)
: m_window(window)
{
assert(m_window != nullptr);
}
private:
std::shared_ptr<Window> m_window;
};
I now spent the last two hours, refactoring all my code, so that I only pass std::shared_ptr and almost
never use the Window class by value. Foo now looks like this:
class
This makes sense, cause even if I pass the Window by value, it usually IS shared
anyway (if I resize it, it's resized for all instances).
However, I also felt that it complicated my code ALOT. For the comparison operator== I now always have to derefence
both sides. When I'm trying to find in an stl container, I now have to use
std::find_if(haystack.begin(), haystack.end(),[&needle](const SharedWindowPtr& ptr) { return *ptr == *needle; });
In addition to that, there's overhead from the shared_ptr. I also run the risk of passing nullptrs, where I want to ensure that doesn't happen. I can check that with assertions, but that isn't foolproof. I could also not pass a shared_ptr but a reference to Foo's constructor and give the Window class a std::unique_ptr<Window> clone() method, but I would have to mock that for every test and if there's a way around it I'd prefer that.
Now I'm wondering if there's any better/cleaner method for handling this kind of problem? Thanks for any advice on this.
EDIT: After thinking about this for a while, I had another idea to approach this.
class WindowHandler
{
public:
virtual void resize(int w, int h) = 0;
virtual void getTitle() = 0;
// ...
};
class DefaultWindowHandler
{
public:
DefaultWindowHandler(HWND hwnd);
virtual void resize(int w, int h) override
{
// ...
}
// ...
protected:
HWND m_hwnd;
};
class Window
{
public:
Window(HWND hwnd)
: m_windowHandler(new DefaultWindowHandler(hwnd))
{
// empty
}
void setWindowHandler(WindowHandler* handler)
{
assert(handler != nullptr);
m_windowHandler.reset(handler);
}
void resize(int w, int h)
{
m_windowHandler->resize(w, h);
}
};
What I like about this, is that I can pass the Window class around by value and still get the benefits of the interface-like behaviour if I need to. What do you think about that, what are the shortcomings? I know that the Window should probably accept a WindowHandler instead of the HWND as the constructor argument, but it's just easier to use the way it is.
Following what as been asked in the comment, it seems like std::unique_ptr will suffer from this option too. If taking by value of the base class, using any pointer or reference is not available, you can always use templates:
template<typename WindowType>
struct Foo {
// Want speed? take by value!
Foo(WindowType window)
: m_window(std::move(window))
{}
private:
WindowType m_window;
};
Then, your class will work with all subtypes of window. But then, using template, the functions being virtual or not is irrelevant.
If you want to limit your class Foo to only accept subtypes of windows, you have two choices: sfinae-like or static_assert
sfinae-like
template<typename, typename = void>
struct Foo;
template<typename WindowType>
struct Foo<WindowType, std::enable_if_t<std::is_base_of<Window, WindowType>::value>> {
Foo(WindowType window)
: m_window(std::move(window))
{}
private:
WindowType m_window;
};
static_assert
template<typename WindowType>
struct Foo {
static_assert(std::is_base_of<Window, WindowType>::value, "WindowType must be a subclass of Window");
Foo(WindowType window)
: m_window(std::move(window))
{}
private:
WindowType m_window;
};
The sfinae-like method will have the advantage of being able to "overload" your class for other types that matches with other conditions, but the static_assert is slightly easier to implement.
I am having a problem accessing an object or its methods in fltk.
I have a Class named MyWindow which is a child class of Fl_Window.
so basically i would like to use an object which is either declared int the main or Mywindow in private section. My problem is that I can't use it that way. It only lets me to use the object if it is declared global. Can i somehow put it on the heap like this: Classname *pointer = new Classname(); ? IF i can where do I do that?
How would the callback function work if i need that object or its functions in the callback?
Should i use a pointer to it in the callback arguements?
lets say i want to click on the button and I need it to do something with the object and change a value.
lots of questions I know, I am really lost.
Can someone just point me to the right direction? Thank you! :)
Simple case for passing data to the GUI
class MyData
{
// The data model
};
class MyWindow: public FL_Window
{
MyData* m_data;
public:
void Data(MyData* data) { m_data = data; }
...
};
int main()
{
MyWindow gui;
MyData data;
// Tell the gui about the data
gui.Data(data);
...
// Setup the dialog
gui.begin();
...
gui.end();
gui.show();
return FL::run();
}
For the callbacks, do it in two stages
class NeedingACallback
{
public:
void Setup()
{
...
FL_xxx* w = new FL_xxx(xpos, ypos, wid, hgt, name);
...
// v Pass the instance to the static
w->callback(_EventCB, this);
}
// The callback
static void _EventCB(FL_Widget* w, void* client)
{
// Convert the void* back to the instance
NeedingACallback* self = reinterpret_cast<NeedingACallback*>(client);
self->EventCB();
}
// Make life simple so you don't have to put self-> in front of
// all the instance data accessed
void EventCB()
{
// Callback for this instance of the class
}
};
EDIT It sounds like you're having multiple instances of data. An alternative technique is to have data as a reference. This must be done in the constructor. This way, m_data and the data in main both refer to the same area of memory.
class MyWindow: public FL_Window
{
MyData& m_data;
public:
MyWindow(int wid, int hgt, MyData& data, const char* title=0)
: FL_Window(wid,hgt,title)
, m_data(data)
{
...
}
};
int main()
{
MyData data;
MyWindow gui(100, 100, data, "Call me Mr");
...
// Setup the dialog
gui.begin();
...
gui.end();
gui.show();
return FL::run();
}
Programming in C++ for Windows although this situation could arise anywhere. This is a simplified version of my problem to keep the question manageable so don't get too caught up on the detail :)
I have a class class Window which contains a windows HWND data item. I want to fully encapsulate that HWND so that the user of the class has to go through the class to perform any operations on that window, so it's stored in a private member variable. I don't want to provide any public "getter" for it as that would break the encapsulation allowing the user to bypass my class.
Now I want to create a class class Direct3d11 to encapsulate some of the directx api. In order to create an instance of this class it requires the HWND of a window so I pass it a Window object in it's constructor.
class Direct3D11
{
public:
Direct3D11(const Window& window);
};
Inside the constructor it has access to the window object, however it requires the HWND contained within in order to be able to physically create the windows objects that the Direct3D11 class will manage, but there is no way for it to obtain that information.
I could add a private getter function to get the HWND to the Window class, and then make the Direct3D11 class a friend class of Window so that it call call the function.
However this doesn't seem very elegant not least because class Window has otherwise no need to know anything at all about class Direct3D11.
Am I missing a better way to achieve this? Friend classes don't appeal, and having a public getter function doesn't much appeal either.
You could create the Direct3D11 class inside Window, since Windows owns the HWND.
Something along these lines:
class Window
{
HWND hwnd;
Direct3D11 d;
public:
Window() : d(hwnd) {}
Direct3D11& getDirect3D()
{
return d;
}
}
In your case I suggest to provide a getter for the HWND because you will probably be needing that more often. Providing the getter does not mean that you take the responsibility of your Window class, it is still responsible for the window's life cycle. You just make it more usable and easier to divide your code in use cases.
That said, here is a more generic approach that you could try:
class Window;
class Direct3D {
public:
void apply(Window &window, HWND hWnd);
};
class Window {
public:
void accept(Direct3D &direct3d) {
direct3d.apply(*this, this->m_hWnd);
}
};
You could maybe have a function on Window called Execute. It would take in a std::function with a placeholder for HWND as a parameter. Window would then call the function with HWND as its only parameter.
This would require c++11, but the code would be similar to :
#include <functional>
#include <iostream>
struct Foo {
explicit Foo(int num) : num_(num) {}
template<typename T>
void execute(std::function<T> f) const { f(num_); }
private:
int num_;
};
struct Bar{
void print_nums(int i,int j)
{
std::cout << "i:" << i << ", " << "j:" << j << std::endl;
}
};
int main()
{
Foo o(42);
Bar b;
//the function we want to execute requires an int
//that Foo knows about
typedef void myFunction(int);
// store the result of a call to std::bind
std::function<myFunction> display_1337_first = std::bind(&Bar::print_nums, b,1337, std::placeholders::_1);
std::function<myFunction> display_1337_last = std::bind(&Bar::print_nums, b, std::placeholders::_1, 1337);
o.execute<myFunction>(display_1337_first);
o.execute<myFunction>(display_1337_last);
return 0;
}
//output:
//i:1337, j:42
//i:42, j:1337
If you are willing to use the friend keyword you can make sure window has no knowledge of the class that needs the hwnd. Just make classes (that window and DirectX inherit from) that handle the actions for you. This allows you to solve the problem for DirectX, AND for the next time it comes around.
Side Rant:
Friend is not a four-letter word. Friend, if used reasonably, is actually a great way to add gradation to C++'s access control (public, friend (when in protected), protected, friend (when in private) , private).
#include <iostream>
class HwndOwner;
class HwndWanter
{
protected:
HwndWanter(){}
int getHwndFromOwner(HwndOwner & owner);
};
class HwndOwner
{
protected:
HwndOwner() : hwnd(42){}
private:
friend class HwndWanter;
int getHwnd()
{
return hwnd;
}
int hwnd;
};
class Window : public HwndOwner
{
//This is not the class you are looking for...
};
class Direct3D : private HwndWanter
{
public:
Direct3D(HwndOwner & owner)
: HwndWanter()
{
std::cout << getHwndFromOwner(owner) << std::endl;
}
};
int HwndWanter::getHwndFromOwner(HwndOwner & owner)
{
return owner.getHwnd();
}
int main()
{
Window window;
Direct3D hwndWanter(window);
}
Output:
42
Let's say we have interface window_creator that responsible for creation of windows. For simplicity it looks like this:
struct window_creator
{
virtual ~window_creator(){}
handle create_window(size_t width, size_t height, bool fullscreen);
};
Also, we have interface for render system that is responsible for rendering in window created by window_creator. It has, for simplicity, following code:
struct render_system
{
virtual ~render_system(){}
void create(handle window_handle);
};
Also, we have 2 implementations for window_creator interface:
struct windows7_creator : public window_creator
{
handle create_window(size_t width, size_t height, bool fullscreen) override {
//calls CreateWindow and returns HWND
}
};
struct macos_creator : public window_creator
{
handle create_window(size_t width, size_t height, bool fullscreen) override {
//calls createWindow_ and returns WindowRef
}
};
And 2 implementations for render_system interface:
struct dx_render_system : public render_system
{
void create(handle window_handle) override{
//calls CreateDevice, etc...
}
};
struct opengl_render_system : public render_system
{
void create(handle window_handle) override{
//calls gl... etc...
}
};
Now on windows platform I can create dx or OpenGL renderer. And on MacOs I can create OpenGL renderer.
The question is: what type of handle should I create to support independence of window_creator and render_system interfaces?
In my current implementation I wrote typedef for handle:
typedef void* handle;
Is there any more elegant solution to this problem?
Generally this sort of thing is done with the following pattern:
#ifdef OS_IS_WINDOWS
#include "WindowsHandle.h"
typedef WindowsHandle NativeHandle;
#elif OS_IS_MAC
#include "MacHandle.h"
typedef MacHandle NativeHandle;
#elif OS_IS_FOO
#include "FooHandle.h"
typedef FooHandle NativeHandle;
#end
You do not need to do runtime dispatching of the different NativeHandles - and in fact without sacrificing type-safety it is nearly impossible to do - as the definition of the platform-specific handles is not available on every platform.
You already know statically at compile-time what operating system you are on, so you may as well take advantage of that.
You shouldn’t use handles at all. Handles (in this context) are a trick employed by non-OO languages to support classes.
But C++ supports classes. So use them.
class window {
// …
virtual ~window() = 0;
};
class windows_window : window { … };
class cocoa_window : window { … };
These classes are RAII objects managing the raw handle resources, and providing convenience interfaces to the appropriate windowing functions.