I'm writing a C++ framework so that I can rewrite some software to work on multiple platforms. The question I have pertains to an implementation of some wrapper classes that use Windows handles. Consider the following code...
class Font
{
public:
Font(const LOGFONT& lf)
{
m_hFont = ::CreateFontIndirect(lf);
}
~Font()
{
::DeleteObject(m_hFont);
}
private:
HFONT m_hFont;
}
I then have a Display class where I might call the following...
LOGFONT lf;
// initialise lf
Display d;
d.SetFont(Font(lf));
d.DrawText(0,0,"Some Text");
The problem of course is that d.SetFont will result in the m_hFont being deleted by the Font class destructor. I appreciate that I could create the font on the heap and let the graphics class be responsible for the Font's overall "lifetime". I guess that this is really a design issue. Is it better to...
Implement reference counting for classes that wrap Windows Handles.
Create wrapper classes on the heap.
Some other method?
I notice that MFC has an explicit DeleteObject in their wrappers but this of course does not result in automatic resource de-allocation.
Any help/advice appreciated.
Thanks
EDIT: I think this is more of a copy constructor question. I.e. My Font class creates a Windows FONT handle, but is destroyed because I pass the Font object to the display by value.
You have at least three options:
Mind "the rule of three": if a class has a non trivial destructor then it should probably also implement a copy constructor and an copy assignment operator. In this case, they should insure that every copy has its own version of a m_hFont.
Use reference counting.
Change Display::SetFont to accept a pointer to a Font or a const reference. That way you can still create the Font "on the stack" and, if you only pass a pointer or a reference to it there will be no copies being made.
EDIT
You might be able to avoid the problem entirely if you make Display::SetFont accept a LOGFONT directly. This way, the Display class itself will manage the fonts (e.g. delete the old font structure and create the new). This option works best if you plan to use the Font object only in the context above (with a Display) and if the font changes are few.
Make the Font class also hold the LOGFONT as a member and generate the HFONT only on demand. When copied, the LOGFONT will be copied and the HFONT be given an invalid value. If the new Font::GetFont is called (say by the Display) then the HFONT will be created. In the Font destructor, if the HFONT is not the invalid value delete it. This will avoid some unnecessary calls to CreateFontIndirect if not all the copies will be used to call GetFont.
That's the nature of Windows. When you use resources in such a way like calling CreateFontIndirect, you'd have have to call DeleteObject or a method of some sort to release resources when you're done. What exactly is the problem? Is your program not behaving as expected? It should be fine unless lf goes out of scope before you use it.
Following advice from the answers and some further thought I have adopted the following approach. I think that the Display class should manage the font's lifetime. Library users would supply font settings to the display class. Basic code is as follows...
struct Typeface
{
bool Bold;
int Width;
int Height;
};
class Font
{
public:
Font();
~Font(); // calls DeleteObject(m_hFont)
HFONT Handle() const { return m_hFont; }
// Create will destroy the current font handle and create a new one
void Create(const Typeface & tc);
private:
HFONT m_hFont;
};
class Display
{
public:
// select font modifies the display's current font
void SelectFont(const Typeface& tf);
// Draw a string using the display's selected font
void DrawString(int x, int y, const String& text);
// Draw a string using the supplied font
void DrawString(int x, int y, const String& text, const Font& font);
private:
Font m_hSelectedFont; // Font handle automatically destroyed
};
I think this is the most convenient solution in C++20:
using XHFONT = unique_ptr<remove_reference_t<decltype(*HFONT())>, decltype([]( HFONT hf ) { hf && DeleteObject( hf ); })>;
unique_ptr<> can only manage data for pointers, but fortunately Windows hanlde are always pointers, usually declared with DECLARE_HANDLE, and you can declare wrappers for any Windows hanlde type except HANDLE because a HANDLE is simply a void-pointer where remove_reference_t<decltype(*HFONT())> doesn't work.
Related
I have a Display class that uses SDL to write pixels to the screen. I'd like another class (Triangle) to be able to use this already existent class object, so I've been trying to pass the object by address.
It's sort of working, in the sense that it is actually calling the methods. However, I was getting a segmentation fault in the DrawPixel function. After checking gdb and checking what values are in the function, I figured out that the color_buffer array does not exist (note that when DrawPixel is called directly from the display class in main it works fine).
After a little more testing, I determined that window_width, window_height etc are not set in the Triangle's version of the Display object. But they do exist in the original Display object.
So I'm assuming that I am not properly passing in my object, but I'm uncertain how to fix this issue as I thought passing by address would work just fine. How can I pass an already existing/instantiated class to another class?
I've also tried putting color_buffer into public variables in case private was causing it, but that didn't help.
Example:
main.cpp
int main() {
Display display;
Triangle triangle(&display);
// This doesn't work
triangle.DrawTriangle(300, 500, 0xFFFFFF00);
// This does work
display.DrawPixel(300, 500, 0xFFFFFF00);
return 0;
}
triangle.hpp
class Triangle {
private:
Display* display;
public:
DrawTriangle(int x, int y, uint32_t color);
};
triangle.cpp
Triangle::Triangle(Display* display) {
display=display;
}
Triangle::DrawTriangle(int x, int y, uint32_t color) {
display->DrawPixel(x, y, color);
}
display.hpp
class Display {
private:
// SDL Stuff defined here
uint32_t* color_buffer;
int window_width = 1920;
int window_height = 1080;
public:
Display();
DrawPixel(int x, int y, uint32_t color);
};
display.cpp
Display::Display() {
// SDL Stuff declared
color_buffer = new uint32_t[window_width * window_height];
}
Display::DrawPixel(int x, int y, uint32_t color) {
// This is receiving the correct values, but doesn't allow me to access
// any index of color_buffer.
color_buffer[(y * window_width) + x] = color;
}
Triangle::Triangle(Display* display) {
display=display;
}
the display is not the member of your class.Use this->display = display instead
You have to use "this" in Triangle constructor. That should solve the problem.
Triangle(Display* display) {
this->display=display;
}
A couple of things to add to the answers above:
use a different naming convention for member variables - this way it is very easy to avoid typos. _display, m_display, Display_ (Clang style =) )
class members are private by default so if you are following convention where attributes are defined on top, there's no need to add private:
Some prefer references (e.g. Display&), mostly to save typing ->, since if `Display goes out of scope it will have the same hilarious effect as passing a pointer.
static analyzers look down on pointer arithmetic(due to possible out-of-bounds writes).
You can use std::array from header:
static constexpr int WIDTH = 1920;
static constexpr int HEIGHT = 1080;
std::array<uint32_t, WIDTH* HEIGHT> m_color_buffer{};
and then either use m_color_buffer[index] = color (no bounds checking, random memory gets written if you write out of bounds in release and normally an exception in debug), or use m_color_buffer.at(index) - slower but this way you get an exception in release mode, but the compiler may complain about the stack size, as the definition is essentially the same as uint32_t buffer[WIDTH*HEIGHT]. std::vector is a better alternative - it hides buffer allocation, manages memory (no need to delete) at expense of the 2 extra pointers for begin and the end of the vector.
The code example lacked a destructor. Every new should have an accompanying delete hence either add it or just switch to a standard library container to avoid the headache =)
Last but not least - both classes override constructors. Display also manages resources. What happens when you copy Display instances? Move them? It is a bit of a headache and leads to a bit of a boilerplate, but it is best to implement Rule of 5 members and avoid accidental surprises =)
PS. C++ is a beautiful language =)
I'm trying to figure out a way to keep track of all the instances of a class I have made, so I can access them at any point using a title string (or int ID)
I decided to use a static vector of pointers to each instance, and then on creating each instance i'd add a pointer to it to the vector.
This works up to a point but at one point the values inside each element of the vector seem to reset/get randomly assigned values and i can't figure out what's happening.
i'm adding the object to the vector here:
SWindow::SWindow(LPCWSTR WindowClass, LPCWSTR Title, UINT Style, int x, int y, int height, int width, HWND hParWnd, HINSTANCE hInstance)
:
x(x),
y(y)
{
hWnd = CreateWindowEx(NULL, WindowClass, Title, Style, x, y, height, width, hParWnd, NULL, hInstance, NULL);
SWindows.push_back(this);
The function at which the values change is:
which is a member of the SWindow class
SWindow.h:
static SWindow* GetSWindow(wstring ws);
SWindow.cpp:
SWindow* SWindow::GetSWindow(wstring ws)
{
for (int i = 0; i < SWindow::SWindows.size(); i++)
{
if (SWindows[i]->title == ws)
{
return SWindows[i];
}
else
{
}
}
return 0;
}
i'm accessing the function from a different class using:
SWindow* pPlayViewer = SWindow::GetSWindow(L"Viewer");
Also if this is a bad way to be doing what i am trying to do, let me know of a better way.
Thanks!
Are you sure that you didn't add stack allocated objects into your static vector? Did you remove pointers when objects are deleted ?
If you want to be more efficient, I can suggest you to use a map, where the key can be your title string/id int and the value the pointer, so that the search would be much faster than parsing the whole array.
There are four main possible causes for the dangling pointers:
you do not remove the instances from the vector upon destruction of an instance
you create instances accross DLL boundaries (and pass the vector arround)
you have a buffer overflow (or similar) in another part of the code and it is overwriting your vector
you are accessing the vector concurrently from multiple threads (and the access to it doesn't look synchronized in your code)
(this is all speculation on my part).
To use such a vector correctly, you will have to do the following:
implement all constructors and destructor for your class (this implies you will also implement the assignment operators, according to the rule of five).
ensure all constructors add this to the vector
ensure destructor removes this from the vector
Also, suggested refactorings:
pass the vector into the object, instead of declaring it as static; this will allow you to decide in client code if you have a single vector, multiple ones, or a window manager object of some sort, that holds a vector internally
group the window creation parameters into a structure, and pass that arround as a parameter
your SWindow class wants to be both a window manager and a window; Extract the window management into a separate object
For a long time I have been thinking about following aspect of classes structure. Let's see we have Style class which stores font size, font color and other font-style settings. We have also a Font class.
And now we have two approaches for describing our tasks. The first one is:
class Style {
public:
unsigned short size;
unsigned short color; // just for example
};
class Font{
private:
Style style;
public:
void setSize( unsigned short fontSize ) {
this->style.size = fontSize;
}
void setColor( unsigned short fontColor ) {
this->style.color = fontColor;
}
void setStyle( Style style ) {
this->style = style;
}
};
The second one is:
class Style {
private:
unsigned short size;
unsigned short color; // just for example
public:
void setSize( unsigned short fontSize ) {
this->style.size = fontSize;
}
void setColor( unsigned short fontColor ) {
this->style.color = fontColor;
}
};
class Font{
private:
Style style;
public:
void setStyle( Style style ) {
this->style = style;
}
};
I use Style-object very often in my app:
Style style;
style.size = 10;
style.color = 02034023; // doesn't matter :)
font.setStyle( style );
So if we define setColor, setFont and other voids in Style class we have loaded them all in our memory (by each copy of Style-object). If we define setColor and others in Font class we have just one copy of setColor loaded in a memory. As I use creating of Style object very often I don't want to load setColor and others in a memory just to have an opportunity to use this class something like this: style.setSize( 10 );. Using such technique I load only one copy of setSize and others in a memory.
What do you think about it? Which structures do you use and why?
Option 1
Pros: Partial encapsulation of the Style object
Cons: You have to provide a method in Font for each field in Style. This may work for simple application like this, but imagine you would have Paragraph class that would have its Font and Content fields (or maybe more). Then you would have to either use option 2 or rewrite all the methods from Font again.
Option 2
Pros: You can fully access the Style object from any level of hierarchy
Cons: You have to instantiate a new object every time you want to change something. Problems with object lifetime/ownership coming in. (Do I delete the style here? Is it referenced somewhere else?). Style object has no encapsulation.
My proposal
Use const-correctness with getters:
class Style
{
public:
unsigned short size;
unsigned short color; // just for example
};
class Font
{
private:
Style style;
public:
const Style& GetStyle() const { return style; }
Style& GetStyle() { return style; }
};
This way you clearly state that the ownership of Style object belongs to Font while also enabling it to be read/changed in given places, i.e.
font.GetStyle().size = 14;
Also you can use function signatures to clearly state hat happens with the Font inside.
void AccessFont(const Font& font)
{
unsigned size = font.GetStyle().size; // works
font.GetStyle().size = 16; // doesn't compile
}
And again, if you came to a hierarchy with Paragraph class as mentioned, you would just add the two getters for Font field. You can then pass around the const and non-const version of Paragraph.
I think either is fine.
If you are going to go with Option 1, I suggest you don't provide a setStyle method so the Style is fully encapsulated. That way, clients of Font don't even need to know that Font contains a Style object. Changes in Style only impact Font and you can even change the implementation of Font to not use a Style object in the future without breaking clients.
If Style is unlikely to change and is just a small object that you are going to pass-by-value then I think Option 2 is fine too.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 4 years ago.
Improve this question
I have a very big design stumbling block in my rendering code. Basically what this is, is not requiring API specific code (such as OpenGL code or DirectX). Now I've thought of numerous ways on how to solve the problem, however I'm not sure which one to use, or how I should improve upon these ideas.
To give a brief example, I will use a Texture as an example. A texture is an object which represents a texture in GPU memory, implementation wise it may be resembled in any particular way, i.e. whether implementation uses a GLuint or LPDIRECT3DTEXTURE9 to resemble the texture.
Now here are the ways I've thought of to actually implement this. I'm quite unsure if there is a better way, or which way is better than another.
Method 1: Inheritance
I could use inheritance, it seems the most obvious choice for this matter. However, this method requires virtual functions, and would require a TextureFactory class in order to create Texture objects. Which would require calls to new for each Texture object (e.g. renderer->getTextureFactory()->create()).
Here's how I'm thinking of using inheritance in this case:
class Texture
{
public:
virtual ~Texture() {}
// Override-able Methods:
virtual bool load(const Image&, const urect2& subRect);
virtual bool reload(const Image&, const urect2& subRect);
virtual Image getImage() const;
// ... other texture-related methods, such as wrappers for
// load/reload in order to load/reload the whole image
unsigned int getWidth() const;
unsigned int getHeight() const;
unsigned int getDepth() const;
bool is1D() const;
bool is2D() const;
bool is3D() const;
protected:
void setWidth(unsigned int);
void setHeight(unsigned int);
void setDepth(unsigned int);
private:
unsigned int _width, _height, _depth;
};
and then in order for OpenGL (or any other API specific) textures to be created, a sub-class would have to be made, such as OglTexture.
Method 2: Use a 'TextureLoader' or some other class
This method is as simple as it sounds, I use another class to handle loading of textures. This may or may not use virtual functions, depending on the circumstance (or whether I feel it is necessary).
e.g. A polymorphic texture loader
class TextureLoader
{
public:
virtual ~TextureLoader() {}
virtual bool load(Texture* texture, const Image&, const urect2& subRect);
virtual bool reload(Texture* texture, const Image&, const urect2& subRect);
virtual Image getImage(Texture* texture) const;
};
If I were to use this, a Texture object would only be a POD type. However, in order for this to work, a handle object/ID would have to be present within the Texture class.
For example, this is how I would more than likely implement it. Although, I may be able to generalise the whole ID thing, using a base class. Such as a Resource base class in which case holds an ID for a graphics resource.
Method 3: The Pimpl Idiom
I could use the pimpl idiom, which implements how to load/reload/etc. textures. This would more than likely require an abstract factory class for creation of textures. I am unsure how this is better than using inheritance. This pimpl idiom could be used in conjunction with Method 2, i.e. Texture objects would have a reference (pointer) to their loader.
Method 4: Using concepts/compile-time polymorphism
I could on the other hand, use compile-time polymorphism and basically use what I presented in the inheritance method, except without declaring virtual functions. This would work, but if I wanted to dynamically switch from OpenGL rendering to DirectX rendering, this would not be the best solution. I would simply put OpenGL/D3D specific code within the Texture class, where there would be multiple texture classes with some-what the same interface (load/reload/getImage/etc.), wrapped inside some namespace (resembling which API it uses, e.g. ogl, d3d, etc.).
Method 5: Using integers
I could just use integers to store handles to texture objects, this seems fairly simple, but may produce some-what "messy" code.
This problem is also present for other GPU resources such as Geometry, Shaders, and ShaderPrograms.
I've also thought of just making the Renderer class handle the creation, loading, and etc. of graphical resources. However this would violate SPR. e.g.
Texture* texture = renderer->createTexture(Image("something.png"));
Image image = renderer->getImage(texture);
Can someone please guide me, I think I'm thinking too heavily about this. I've tried observing various rendering engines, such as Irrlicht, Ogre3D, and others I have found online. Ogre and Irrlicht use inheritance, however I am unsure that this is the best route to take. As some others just use void*, integers, or just put API specific (mainly OpenGL) code within their classes (e.g. GLuint directly within the Texture class). I really cannot decide which design would be the most appropriate for me.
The platforms I am going to target are:
Windows/Linux/Mac
iOS
Possibly Android
I have considered to just use OpenGL specific code, as OpenGL works for all of those platforms. However, I feel that if I do that I will have to change my code quite a lot if I wish to port to other platforms that cannot use OpenGL, such as the PS3. Any advice on my situation will be greatly appreciated.
Think of it from a high-level point of view. How will your rendering code work with the rest of you game/application model? In other words, how do you plan to create objects in your scene and to what degree of modularity? In my previous work with engines, the end result of a well-designed engine generally has a step-by-step procedure that follows a pattern. For example:
//Components in an engine could be game objects such as sprites, meshes, lights, audio sources etc.
//These resources can be created via component factories for convenience
CRenderComponentFactory* pFactory = GET_COMPONENT_FACTORY(CRenderComponentFactory);
Once a component has been obtained there are usually a variety of overloaded methods you could use to construct the object. Using a sprite as an example, a SpriteComponent could contain everything potentially needed by a sprite in the form of sub-components; like a TextureComponent for instance.
//Create a blank sprite of size 100x100
SpriteComponentPtr pSprite = pFactory->CreateSpriteComponent(Core::CVector2(100, 100));
//Create a sprite from a sprite sheet texture page using the given frame number.
SpriteComponentPtr pSprite = pFactory->CreateSpriteComponent("SpriteSheet", TPAGE_INDEX_SPRITE_SHEET_FRAME_1);
//Create a textured sprite of size 100x50, where `pTexture` is your TextureComponent that you've set-up elsewhere.
SpriteComponentPtr pSprite = pFactory->CreateSpriteComponent(Core::CVector2(100, 50), pTexture);
Then it's simply a matter of adding the object to the scene. This could be done by making an entity, which is simply a generic collection of information that would contain everything needed for scene manipulation; position, orientation, etc. For every entity in your scene, your AddEntity method would add that new entity by default to your render factory, extracting other render-dependent information from sub-components. E.g:
//Put our sprite onto the scene to be drawn
pSprite->SetColour(CColour::YELLOW);
EntityPtr pEntity = CreateEntity(pSprite);
mpScene->AddEntity(pEntity);
What you then have is a nice way of creating objects and a modular way of coding your application without having to reference 'draw' or other render-specific code. A good graphics pipeline should be something along the lines of:
This is a nice resource for rendering engine design (also where the above image is from). Jump to page 21 and read onwards where you'll see in-depth explainations of how scenegraphs operate and general engine design theory.
I don't think there's any one right answer here, but if it were me, I would:
Plan on using only OpenGL to start with.
Keep rendering code separate from other code (that's just good design), but don't try to wrap it in an extra layer of abstraction - just do whatever is most natural for OpenGL.
Figure that if and when I was porting to PS3, I would have a much better grasp of what I need my rendering code to do, so that would be the right time to refactor and pull out a more abstract interface.
I've decided to go for a hybrid approach, with method (2), (3), (5) and possibly (4) in the future.
What I've basically done is:
Every resource has a handle attached to it. This handle describes the object. Each handle has an ID associated with it, which is a simple integer. In order to talk to the GPU with each resource, an interface for each handle is made. This interface is at the moment abstract, but could be done with templates, if I choose to do so in the future. The resource class has a pointer to an interface.
Simply put, a handle describes the actual GPU object, and a resource is just a wrapper over the handle and an interface to connect the handle and the GPU together.
This is what it basically looks like:
// base class for resource handles
struct ResourceHandle
{
typedef unsigned Id;
static const Id NULL_ID = 0;
ResourceHandle() : id(0) {}
bool isNull() const
{ return id != NULL_ID; }
Id id;
};
// base class of a resource
template <typename THandle, typename THandleInterface>
struct Resource
{
typedef THandle Handle;
typedef THandleInterface HandleInterface;
HandleInterface* getInterface() const { return _interface; }
void setInterface(HandleInterface* interface)
{
assert(getHandle().isNull()); // should not work if handle is NOT null
_interface = interface;
}
const Handle& getHandle() const
{ return _handle; }
protected:
typedef Resource<THandle, THandleInterface> Base;
Resource(HandleInterface* interface) : _interface(interface) {}
// refer to this in base classes
Handle _handle;
private:
HandleInterface* _interface;
};
This allows me to extend quite easily, and allows for syntax such as:
Renderer renderer;
// create a texture
Texture texture(renderer);
// load the texture
texture.load(Image("test.png");
Where Texture derives from Resource<TextureHandle, TextureHandleInterface>, and where renderer has the appropriate interface for loading texture handle objects.
I have a short working example of this here.
Hopefully this works, I may choose to redesign it in the future, if so I will update. Criticism would be appreciated.
EDIT:
I have actually changed the way I do this again. The solution I am using is quite similar to the one described above, but here is how it is different:
The API revolves around "backends", these are objects that have a common interface and communicate with a low-level API (e.g. Direct3D or OpenGL).
Handles are no longer integers/IDs. A backend has specific typedef's for each resource handle type (e.g. texture_handle_type, program_handle_type, shader_handle_type).
Resources do not have a base class, and only require one template parameter (a GraphicsBackend). A resource stores a handle and a reference to the graphics backend it belongs to. Then the resource has a user-friendly API and uses the handle and graphics backend common interface to interact with the "actual" resource. i.e. resource objects are basically wrappers of handles that allow for RAII.
A graphics_device object is introduced to allow construction of resources (factory pattern; e.g. device.createTexture() or device.create<my_device_type::texture>(),
For example:
#include <iostream>
#include <string>
#include <utility>
struct Image { std::string id; };
struct ogl_backend
{
typedef unsigned texture_handle_type;
void load(texture_handle_type& texture, const Image& image)
{
std::cout << "loading, " << image.id << '\n';
}
void destroy(texture_handle_type& texture)
{
std::cout << "destroying texture\n";
}
};
template <class GraphicsBackend>
struct texture_gpu_resource
{
typedef GraphicsBackend graphics_backend;
typedef typename GraphicsBackend::texture_handle_type texture_handle;
texture_gpu_resource(graphics_backend& backend)
: _backend(backend)
{
}
~texture_gpu_resource()
{
// should check if it is a valid handle first
_backend.destroy(_handle);
}
void load(const Image& image)
{
_backend.load(_handle, image);
}
const texture_handle& handle() const
{
return _handle;
}
private:
graphics_backend& _backend;
texture_handle _handle;
};
template <typename GraphicBackend>
class graphics_device
{
typedef graphics_device<GraphicBackend> this_type;
public:
typedef texture_gpu_resource<GraphicBackend> texture;
template <typename... Args>
texture createTexture(Args&&... args)
{
return texture{_backend, std::forward(args)...};
}
template <typename Resource, typename... Args>
Resource create(Args&&... args)
{
return Resource{_backend, std::forward(args)...};
}
private:
GraphicBackend _backend;
};
class ogl_graphics_device : public graphics_device<ogl_backend>
{
public:
enum class feature
{
texturing
};
void enableFeature(feature f)
{
std::cout << "enabling feature... " << (int)f << '\n';
}
};
// or...
// typedef graphics_device<ogl_backend> ogl_graphics_device
int main()
{
ogl_graphics_device device;
device.enableFeature(ogl_graphics_device::feature::texturing);
auto texture = device.create<decltype(device)::texture>();
texture.load({"hello"});
return 0;
}
/*
Expected output:
enabling feature... 0
loading, hello
destroying texture
*/
Live demo: http://ideone.com/Y2HqlY
This design is currently being put in use with my library rojo (note: this library is still under heavy development).
I'm not having a lot of luck in C++ getting one of my classes to see/reference/copy data from one of my other classes so it can use it.
Basically I get the error 'Core' does not name a type or when I try to forward declare (http://stackoverflow.com/questions/2133250/does-not-name-a-type-error-in-c) I get field 'core' has incomplete type
I'm guessing the second error is due to the class not really being initialized possibly, so it has nothing to get? I dunno :( (see code at the bottom)
In my C# games I would normally create a "core" class, and then within that I would start other classes such as 'entities', 'player', 'weapons', etc. When I start these other classes I would pass "this"
public WeaponManager c_WeaponManager;
...
c_WeaponManager = new WeaponManager(this);
so I could always access public values of any class from anywhere as long as it passed through core.
Eg:
So when I do my update through the 'weapon' class, and it detects its hit the player, I'd simply get a function within that class to...
core.playerClass.deductHealth(damageAmmount);
..or something like that.
It allowed me to keep lots of variables I wanted to access globally neatly tucked away in areas that I felt were appropriate.
I know this isn't a good method of programming, but its what I'm fairly comfortable with and I mainly do hobby programming so I like being able to access my data quickly without bureaucratic Get() and Set() functions handing data from one class to another and another. Also I'm still fumbling my way through header files as they seem to be a pain in the ass
//-----------[In vid_glinit.h]-------------------
include "core.h"
class Vid_glInit
{
public:
RECT glWindowRect;
Core core;
Vid_glInit();
~Vid_glInit();
void StartGl(HWND _hGameWindow, int resolutionX, int resolutionY);
private:
};
//------------[in core.h]----------
include "vid_glinit.h"
class Core
{
public:
Vid_glInit vid_glinit(this);
enum GAME_MODE
{
INIT,
MENUS,
GAMEPLAY
};
GAME_MODE gameMode;
HWND hGameWindow;
HGLRC hGameRenderContext; // Permanent Rendering Context
HDC hGameDeviceContext; // Private GDI Device Context
//functions go here
Core();
~Core();
void testFunc();
void Run();
void Update();
void Render();
void StartGl(int resoultionX, int resolutionY);
private:
};
The goal is that when I start OpenGl, instead of having lots of little functions to pass data around I simply tell the glFunctions who need the Device or Rendering context to use core.hGameDeviceContext , if that makes sense
The problem is that you've got
class Vid_glInit
{
public:
Core core;
which means allocate a full copy of the Core object inline inside this class, and also
class Core
{
public:
Vid_glInit vid_glinit(this);
which means allocate a full copy of the Vid_glInit object inline inside the class - and this is now circular, and neither structure's size can be computed.
You probably actually want to allocate at least one of them by reference or pointer, i.e.
class Core
{
public:
Vid_glInit* vid_glinit; // pointer: access properties as core.vid_glinit->foo
Vid_glInit& vid_glinit; // reference: properties are core.vid_glinit.foo
In that case you can use the class Vid_glInit; simple forward declaration because these are just pointers internally and the size of a pointer is fixed regardless of the structure behind it, i.e. C++ can lay out the Core class in memory without full knowledge of the Vid_glInit structure.