Working on a simple game in c++ but I keep stumbling on a cross #include problem. Essentially the problem is like this:
I have a Chunk class that depends on Tile and Entity but Entity also depends on Chunk.
Entity.hpp
#include "Chunk.hpp"
class Entity {
public:
Chunk in_chunk;
};
Chunk.hpp
#include "Entity.hpp" // <-- not possible
class Chunk {
public:
std::vector<std::vector<Tile>> tiles;
std::vector<Entity> needs_update;
};
Now I know this question has been asked before and that this can be solved by using forward declarations and pointing to the class, but, as far as I am aware, this will also mean that everytime I need to access this vector filled with Tiles and its needs_update member I will need to do so by using pointers.
This seems like a very bad solution and I feel like there must be a better way.
So, is the only solution by pointing to the class or is there another way to get around this?
Mind you, I am quite new to c++ and just starting to grasp the concepts of pointers and references, if I am missing something trivial here please point me in the right direction and perhaps I can fix this myself.
So, is the only solution by pointing to the class or is there another way to get around this?
Forward declarations do not require usage of pointers. See fixed example on wandbox.
(Since C++17 std::vector actually can hold incomplete (forward declared) types).
Never the less, your example is "strange". Entity is an owner of Chunk, but Chunk contains Entities by value? It seems that either Entity should refer to a chunk (by reference/pointer or some other mechanism like id) or Chunk should refer to Entities that needs to be updated.
Right now it is something like this:
Every entity contains (distinct) Chunk.
Every Chunk contains two-dimensional vector of (distinct) tiles and vector of (distinct) Entities.
Every Entity from that vector contains (distinct) Chunk and so on.
If two entities should be able to "refer" to one chunk then that chunk should be outside of an entities. If two Chunks should be able to "refer" to same entities then that Entities should be stored outside Chunks and Chunk refer to them by pointer, reference, smart-pointer or an id.
What you have there is a circular dependency, which means that each file includes itself. The most common way to resolve this is by using forward declarations.
as far as I am aware, this will also mean that everytime I need to access this vector filled with Tiles and its needs_update member I will need to do so by using pointers
Nope, not at all. What your doing by a forward declaration is that you tell the compiler "Hey dude, there's a class/ struct named 'something' somewhere. Just leave it to the linker to figure it out". Then the compiler compiles it fine and its the duty of the linker to link them to the class definition (the linker will throw an error if it cant find the definition).
The only down side is that you need to include the class header if your planning on accessing the members of that forward declared class/ struct.
So, is the only solution by pointing to the class or is there another way to get around this?
My approach would be something like this,
Lets say that Chunk.hpp has the forward declaration of Entity. Then when accessing the members of Entity using a function, move the function definition to a source file (as you would normally do except for templated classes) and include the Entity.hpp file there so that it can access the member functions of Entity.
Related
Basically, I have a base class called materials. Materials has many virtual functions, one of them is called a "Double DVD" (Which is a type of material, but is made up of two DVD's which are another material).
So at first I thought I'd store it as either a pair/vector of materials in a derived class called "Set" and have a virtual function defined in material.h that would return a vector of pointers to the two (or more) DVD objects stored.
virtual std::vector<DVD *> getPointers() { return std::vector<DVD *>(); }
However, the problem is that this necessitated the inclusion of "DVD.h" into Materials.h like this:
#ifndef CWK_MAT_H
#define CWK_MAT_H
#include "DVD.h"
#include <string>
#include <vector>
namespace MATERIALS
{
This caused the code to break in absolutely spectacular ways. Is there any way to get around this problem? I need the virtual method to get the pointers to be in the Materials class so that I can access it from this vector:
std::vector<Material *> vect;
As in
vect[1]->getPointers()
I tried to change it to a vector of materials but then it breaks (For some reason makes Visual Studio basically freeze, saying it's updating IntelliSense forever) when I change it to that in the derived class "set" (Set derives from Material, DoubleDVD derives from Set)
Is there any way to do this?
You can forward declare any class that you only use pointers or references to, instead of including the .h file with the full type information. simply type class DVD; before you use the vector of DVD pointers. A forward declaration is basically telling the compiler "hey, trust me, this type exists and I'll tell you more about it when you actually need that information". It works because pointers (and references, which are basically just fancy pointers) are always the same size, so the compiler doesn't actually NEED any more information to deal with them.
https://stackoverflow.com/a/4757718/493106
Also, by putting the code for functions in a .cpp file instead (where possible - templated class methods are sometimes not possible to do this with), you get rid of a lot of situations where you end up with circular includes, since nothing should be #include'ing .cpp files.
So far, I've been using classes the following way:
GameEngine.h declares the class as follows
class GameEngine {
public:
// Declaration of constructor and public methods
private:
InputManager inputManager;
int a, b, c;
// Declaration of private methods
};
My GameEngine.cpp files then just implement the methods
#include "____.h"
GameEngine::GameEngine() {
}
void GameEngine::run() {
// stuff
}
However, I've recently read that variable declarations are not supposed to be in the header file. In the above example, that would be an inputManager and a, b, c.
Now, I've been searching for where to put the variable declarations, the closest answer I found was this: Variable declaration in a header file
However, I'm not sure if the use of extern would make sense here; I just declare private variables that will only be used in an instance of the class itself. Are my variable declarations in the header files fine? Or should I put them elsewhere? If I should put them in the cpp file, do they go directly under the #include?
Don't confuse a type's members with variables. A class/struct definition is merely describing what constitutes a type, without actually declaring the existence of any variables, anything to be constructed on memory, anything addressable.
In the traditional sense, modern class design practices recommend you pretend they are "black boxes": stuff goes in, they can perform certain tasks, maybe output some other info. We do this with class methods all the time, briefly describing their signature on the .h/.hpp/.hxx file and hiding the implementation details in the .cpp/.cc/.cxx file.
While the same philosophy can be applied to members, the current state of C++, how translation units are compiled individually make this way harder to implement. There's certainly nothing "out of the box" that helps you here. The basic, fundamental problem is that for almost anything to use your class, it kind of needs to know the size in bytes, and this is something constrained by the member fields and the order of declaration. Even if they're private and nothing outside the scope of the type should be able to manipulate them, they still need to briefly know what they are.
If you actually want to hide this information to outsiders, certain idioms such as PImpl and inlined PImpl can help. But I'd recommend you don't go this way unless you're actually:
Writing a library with a semi-stable ABI, even if you make tons of changes.
Need to hide non-portable, platform-specific code.
Need to reduce pre-processor times due to an abundance of includes.
Need to reduce compile times directly impacted by this exposure of information.
What the guideline is actually talking about is to never declare global variables in headers. Any translation unit that takes advantage of your header, even if indirectly, will end up declaring its own global variable as per header instructions. Everything will compile just fine when examined individually, but the linker will complain that you have more than one definition for the same thing (which is a big no-no in C++)
If you need to reserve memory / construct something and bind it to a variable's name, always try to make that happen in the source file(s).
Class member variables must be declared in the class definition, which is usually in a header file. This should be done without any extern keywords, completely normally, like you have been doing so far.
Only variables that are not class members and that need to be declared in a header file should be declared extern.
As a general rule:
Variables that are to be used with many functions in the same class go in the class declaration.
Temporary variables for individual functions go in the functions themselves.
It seems that InputManager inputManager; belongs in the class header.
int a, b, c; is harder to know from here. What are they used for? They look like temporary variables that would be better off in the function(s) they're used in, but I can't say for sure without proper context.
extern has no use here.
Edit For Clarification:
Is there a way to split a class's header across multiple files, such that other classes can include only the parts of that class's implementation it's supposed to be allowed to use?
----Below is specific details to my desired implementation:---- NOT A NECESSARY READ!
Anyways, I'm creating an entity-component system. I would like to structure it as follows:
There is an 'EntityPool' object that exists mainly as a memory store/manager for entities and their components. I would like to have a specified degree of access from my 'Game' class (for example, the ability to construct/destruct the pool, and the ability to access arrays of components ei the ability to iterate through all 'renderable' components).
There is a base class of 'EntityFactory' that I would like to have a greater degree of access to the entity pool. It would be used by the 'Game' class as follows:
GruntEntityFactory ef(&EntityPool); //GruntEntityFactory inherits from EntityFactory
ef.produce();
The Entity Factory would then use its access to the Entity Pool to create the necessary components and put them in place.
The thing to note here is that 'Game' would have access only to create the EntityPool and read its contents, but would NOT be able to directly alter its contents. Everything that inherits EntityFactory, on the other hand, I would like to give access to manage EntityPool's contents.
Is there a way I can include a different EntityPool header in each of the files, such that each is only 'aware' of the functions it has access to? Is that the best way to do this (assuming it's possible)?
Also- I realize this tightly couples the EntityPool and EntityFactories. That is intentional. And also, I would like to not have to list every EntityFactory I make as a friend class in EntityPool.
Thanks!
Example code for clarification
//In my Game Class
#include "entitypool.h"
#include "entityfactory_grunt.h"
...
EntityPool ep(); //Construct an EntityPool
GruntEntityFactory gef(&ep); //Pass an EntityPool pointer to an EntityFactory
gef.produce(); //Call produce on GruntEntityFactory, and have it add appropriate components to the EntityPool
//I would like this next line to not be allowed. Game shouldn't be able to
//directly manipulate the components/ other internal EntityPool structure.
//However, I WOULD like EntityFactories to retain the ability to do so.
//(otherwise, how would EntityFactory.produce() work?)
ep.addComponent(PhysicsComponent pc(1, 2, 3));
//I WOULD like Game to be able to access certain functions of EntityPool
for(int i = 0; i < ep.numPhysicsComponents; i++)//Like the count of entities
physicsSolver.update(ep.physicsComponents[i]);//And the ability to update/render components
Ok. So hopefully that's sensible enough of an example to get an idea for what I want. The reason for the title is that my first intuition on how to achieve this would be to have 2 header files.
//EntityPool_GameAccess.h
//This file would contain prototypes for the functions utilized by Game, but NOT the ones
//that game is not allowed to see.
class EntityPool
{
public:
int numPhysicsComponents();
PhysicsComponent getPhysicsComponent(int i);
};
and
//EntityPool_FactoryAccess.h
//This file would contain prototypes for the functions that only ought be used
//by classes specifically built to manipulate entitypool
class EntityPool
{
public:
void addPhysicsComponent(PhysicsComponent pc);
int numPhysicsComponents();
PhysicsComponent getPhysicsComponent(int i);
};
Obviously these examples are simplified. Hopefully I'm still getting the idea across: I would like a class with certain functions that are accessible to certain classes, and other functions that are accessible to other classes.
Ok. I've finally found an answer in another question on StackOverflow: Making classes public to other classes in C++
The bottom part of Patrick's answer:
Unfortunately, there is no way in C++ to make only a part of your class public to a limited set of other classes.
I'm creating a class called ImageLoader that will be used to load various image formats. For various image formats there are certain structs used. For example with bmp files you have a BITMAPFILEHEADER struct and two others.
What I want to know is, when I'm putting my class definition in the header file, do I make the struct typedefs part of the class definition, or should they be separate, outside the class definition?
I'm not sure because if I was just declaring a struct variable, that would obviously happen in the class, but because I'm defining a type, I'm not sure if it's considered good design to define a type inside a class.
My general rule is that if it will only be used in conjunction with that class, then declare it inside (it implies ownership); otherwise declare it separately.
You get better encapsulation if you leave out everything from the header that you possibly can. Even if some methods of your class need parameters or return types of the struct, you might get away with a forward declaration.
The only time you need to put it in the header is when it's part of the public interface.
As to whether it goes in the class or not, consider whether it's useful on its own or if it is totally subservient to the class. If it can stand alone it should probably go in its own header.
I would not say that declaring a type in a class is an indicator of bad design. Assuming that your mention of "design" means something along the lines of "readability", I would be a stickler for consistency and insist that the same relationships be expressed in the same way.
Otherwise, you are not going to be struck down by a divine wrath for nesting types (Considering SGI is not a smoldering crater). This is pretty context-centric, so there are no hard and fast rules outside of what you define based on your requirements.
If client accessibility is not an issue, I declare most everything in an appropriate scope in headers and just document what my code means. Again, this is if I do not have strict usage/readability guidelines to enforce. I'd go with Mark's suggestion if I did.
Two cents: You could try enumerating image types and using one public struct for config data so that you could justify pulling everything else behind closed doors.
BITMAPFILEHEADER is a structure defined in the Win32 Platform SDK. I'm not sure I've understood your request about it and your class...
In general, if you are defining structures that are not exposed to the client of your class, I'd define them in the private part of your class, or in a sub-namespace Details in your header file, e.g.:
namespace YourCoolLibrary
{
namespace Details
{
struct SomeInternalStructure
{
...
};
} // namespace Details
class YourCoolClass
{
...
private:
Details::SomeInternalStructure m_something;
};
} // namespace YourCoolLibrary
There are even many more choices. If you put it in the class you have to choose if it's public, protected, or private making the class definition visible for every user of the class, only derived classes or no other classes.
If you do not need the details of the class definition I'd put only forward declarations into ImageLoader to keep it simpler. The full definition of the inner class then goes into the implementation file.
My rule of thumb is to make names as local as possible, so if I use it accidentally at the wrong place the compiler will complain.
If the typedef logically belongs into the class you are creating, put it inside; if it would make sense on a global level, leave it outside.
Are (seemingly) shady things ever acceptable for practical reasons?
First, a bit of background on my code. I'm writing the graphics module of my 2D game. My module contains more than two classes, but I'll only mention two in here: Font and GraphicsRenderer.
Font provides an interface through which to load (and release) files and nothing much more. In my Font header I don't want any implementation details to leak, and that includes the data types of the third-party library I'm using. The way I prevent the third-party lib from being visible in the header is through an incomplete type (I understand this is standard practice):
class Font
{
private:
struct FontData;
boost::shared_ptr<FontData> data_;
};
GraphicsRenderer is the (read: singleton) device that initializes and finalizes the third-party graphics library and also is used to render graphical objects (such as Fonts, Images, etc). The reason it's a singleton is because, as I've said, the class initializes the third-party library automatically; it does this when the singleton object is created and exits the library when the singleton is destroyed.
Anyway, in order for GR to be able to render Font it must obviously have access to its FontData object. One option would be to have a public getter, but that would expose the implementation of Font (no other class other than Font and GR should care about FontData). Instead I considered it's better to make GR a friend of Font.
Note: Until now I've done two things that some may consider shady (singleton and friend), but these are not the things I want to ask you about. Nevertheless, if you think my rationale for making GR a singleton and a friend of Font is wrong please do criticize me and maybe offer better solutions.
The shady thing. So GR has access to Font::data_ though friendship, but how does it know exactly what a FontData is (since it's not defined in the header, it's an incomplete type)? I'll just show the code and the comment that includes the rationale...
// =============================================================================
// graphics/font.cpp
// -----------------------------------------------------------------------------
struct Font::FontData
: public sf::Font
{
// Just a synonym of sf::Font
};
// A redefinition of FontData exists in GraphicsRenderer::printText(),
// which will have to be modified as well if this definition is modified.
// (The redefinition is called FontDataSurogate.)
// Why not have FontData defined only once in a separate header:
// If the definition of FontData changes, most likely printText() text will
// have to be altered also regardless. Considering that and also that FontData
// has (and should have) a very simple definition, a separate header was
// considered too much of an overhead and of little practical advantage.
// =============================================================================
// graphics/graphics_renderer.cpp
// -----------------------------------------------------------------------------
void GraphicsRenderer::printText(const Font& fnt /* ... */)
{
struct FontDataSurogate
: public sf::Font {
};
FontDataSurogate* suro = (FontDataSurogate*)fnt.data_.get();
sf::Font& font = (sf::Font)(*suro);
// ...
}
So that's the shady thing I'm trying to do. Basically what I want is a review of my rationale, so please tell me if you think I've done something horrendous or if not confirm my rationale so I can be a bit surer I'm doing the right thing. :) (This is my biggest project yet and I'm only at the beginning so I'm kinda feeling things in the dark atm.)
In general, if something looks sketchy, I've found that it's often worth going back a few times and trying to figure out exactly why that's necessary. In most cases, some kind of fix pops up (maybe not as "nice", but not relying on any kind of trick).
Now, the first issue I see in your example is this bit of code:
struct FontDataSurogate
: public sf::Font {
};
occurs twice, in different files (neither being a header). That may come back and be a bother when you change one but not the other in the future, and making sure both are identical will very likely be a pain.
To solve that, I would suggest putting the definition to FontDataSurogate and the appropriate includes (whatever library/header defines sf::Font) in a separate header. From the two files that need to use FontDataSurogate, include that definition header (not from any other code files or headers, just those two).
If you have a main class declaration header for your library, place the forward declaration for the class there, and use pointers in your objects and parameters (regular pointers or shared pointers).
You can then use friend or add a get method to retrieve the data, but by moving the class definition to its own header, you've created a single copy of that code and have a single object/file that's interfacing with the other library.
Edit:
You commented on the question while I was writing this, so I'll add on a reply to your comment.
"Too much overhead" - more to document, one more thing to include, the complexity of the code grows, etc.
Not so. You will have one copy of the code, compared to the two that must remain identical now. The code exists either way, so it needs documented, but your complexity and particularly maintenance is simplified. You do gain two #include statements, but is that such a high cost?
"Little practical advantage" - printText() would have to be modified every time FontData is modified regardless of whether or not it's defined in a separate header or not.
The advantage is less duplicate code, making it easier to maintain for you (and others). Modifying the function when the input data changes is not surprising or unusual really. Moving it to another header doesn't cost you anything but the mentioned includes.
friend is fine, and encouraged. See C++ FAQ Lite's rationale for more info: Do friends violate encapsulation?
This line is indeed horrendous, as it invokes undefined behavior: FontDataSurogate* suro = (FontDataSurogate*)fnt.data_.get();
You forward declare the existence of the FontData struct, and then go on to fully declare it in two locations: Font, and GraphicsRenderer. Ew. Now you have to manually keep these exactly binary compatible.
I'm sure it works, but you're right, it is kindof shady. But whenever we say such-and-such is eeevil, we mean to avoid a certain practice, with the caveat that sometimes it can be useful. That being said, I don't think this is one of those times.
One technique is to invert your handling. Instead of putting all of the logic inside GraphicsRenderer, put some of it inside Font. Like so:
class Font
{
public:
void do_something_with_fontdata(GraphicsRenderer& gr);
private:
struct FontData;
boost::shared_ptr<FontData> data_;
};
void GraphicsRenderer::printText(const Font& fnt /* ... */)
{
fnt.do_something_with_fontdata(*this);
}
This way, the Font details are kept within the Font class, and even GraphicsRenderer doesn't need to know the specifics of the implementation. This solves the friend issue too (although I don't think friend is all that bad to use).
Depending on how your code is laid out, and what it's doing, attempting to invert it like this may be quite difficult. If that is the case, simply move the real declaration of FontData to its own header file, and use it in both Font and GraphicsRenderer.
You've spent a lot more effort asking this question then you've supposedly saved by duplicating that code.
You state three reasons you didn't want to add the file:
Extra include
Extra Documentation
Extra Complexity
But I would have to say that 2 and 3 are increased by duplicating that code. Now you document what its doing in the original place and what the fried monkey its doing defined again in another random place in the code base. And duplicating code can only increase the complexity of a project.
The only thing you are saving is an include file. But files are cheap. You should not be afraid of creating them. There is almost zero cost (or at least there should be) to add a new header file.
The advantages of doing this properly:
The compiler doesn't have to make the definition you give compatible
Someday, somebody is going to modify the FontData class without modifying PrintText(), maybe they should modify PrintText(), but they either haven't done it yet or don't know that they need to. Or perhaps in a way that simply hasn't occoured to additional data on FontData make sense. Regardless, the different pieces of code will operate on different assumptions and will explode in a very hard to trace bug.