I'm simply passing a pointer to an instance of a class to another class but I just can't access anything from the pointer. It's really, really starting to bug me. Here's a really simple example of the code:
//manager.h
Game* game = new Game();
BClass* bc = new BClass(this);
//bclass.h
BClass(Manager* bcref) {
bcref->game //error
bcref->bc //error
}
//The errors are "left of ->x must point to class/struct/union/generic type.
I understand this is because I need to forward declare but adding things such as "class Manager;" at the top doesn't seem to do anything. I still can't access a member or method. I'm really trying to do something that's incredibly simple and I've been pulling my hair out for hours. I've googled and tried pretty much everything I can.
Any ideas?
In order to be able to do this:
BClass* bc = new BClass(this);
Manager needs the definition of BClass. This is presumably in bclass.h. In order to do this
bcref->game;
BClass needs the definition of Manager. This is presumably in manager.h.
So you would need include each header in the other, which would lead to a cyclic include dependency. What you really need to do is break the dependency by moving the implementations to bclass.cpp and manager.cpp respectively, and use only forward declarations in your headers.
Related
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.
I've made a programm with libraries.
One library has a interface for to include a header for an extern programm call:
class IDA{
private:
class IDA_A;
IDA_A *p_IDA_A;
public:
IDA();
~IDA();
void A_Function(const char *A_String);
};
Then I opened the header with Kate and placed
class IDA_A;
IDA_A *p_IDA_A;
into the public part.
And this worked?! But why? And can I avoid that?
Greeting
Earlybite
And this worked?!
Yes
But why?
private, protected and public are just hints to the C+++ compiler how the data structure is supposed to be used. The C++ compiler will error out if piece of C++ source doesn't follow this, but that's it.
It has no effect whatsoever on the memory layout. In particular the C++ standard mandates, that member variables of a class must be laid out in memory in the order they are declared in the class definition.
And can I avoid that?
No. In the same way you can not avoid, that some other piece of code static_casts a (opaque) pointer to your class to char* and dumps it out to a file as is, completely with vtable and everything.
If you really want to avoid the user of a library to "look inside" you must give them some handle value and internally use a map (std::map or similar) to look up the actual instance from the handle value. I do this in some of the libraries I develop, for robustness reasons, but also because some of the programming environments there are bindings for don't deal properly with pointers.
Of course this works. The whole private-public stuff is only checked by the compiler. There are no runtime-checks for this. If the library is already compiled, the user only needs the library file (shared object) and the header files for development. If you afterwards change the header file in the pattern you mentioned, IDA_A is considered public by the compiler.
How can you avoid that? There is no way for this. If another user changes your headerfile, you can do nothing about it. Also is the question: Why bother with it? It can have very ugly side-effects if the headerfile for an already compiled lib is been changed. So the one who changes it also has to deal with the issues. There is just some stuff you dont do. One of them is moving stuff in headers around for libraries (unless you are currently developing on that library).
You've got access to the p_IDA_A member variable, and this is always possible in the manner you've outlined. But it is of type IDA_A, which for which you only have a declaration, but not the definition. So you can not do anything meaningful with it. (This method of data hiding is called the pimpl idiom).
I currently have a problem with mutual inclusion in a project of mine (C++).
Normally, if I had a mutual inclusion problem, I'd easily solve it by either forward declaration or redesigning the classes a bit. But this time, I'm stuck:
I have a class called Game, which creates and launches core game systems, where one of these is called GraphicsSystem.
In the Game constructor, a GraphicsSystem object is dynamically created and stored in a GraphicsSystem* pointer. Looks like this:
Game::Game ()
{
gfxSys = new GraphicsSystem(80, new Camera());
}
Now my GraphicsSystem class needs to access a Game class's method at one point to get the player object, which is stored within the Game object. The respective part looks like this (Game is btw a singleton!):
void GraphicsSystem::handleFrame ()
{
ElementList elements = Game::instance()->getPlayer()->getEnvironment()->getElements();
}
Now I tried forward declaration in both directions already, but that wouldn't satisfy the compiler. I could of course also just put the player pointer into the graphics system, but I really don't want to do that, since he doesn't belong there.
Is there any way to resolve this without me having to change the design too much? I'm really stumped right now, so I hope you guys can help me.
I'm using Visual Studio 2010 (Visual C++).
Thank you in advance!
Chris
Forward declare GraphicsSystem in Game.h. Include Game.h in GraphicsSystem.h if it needs it. Include Game.h and GraphicsSystem.h in Game.cpp. Include Game.h and GraphicsSystem.h in GraphicsSystem.cpp.
That should work based off the code you posted.
There are two main ways to break circular dependencies in C++.
1) Create a 'interface' class which lists the methods implemented by your real class and which your real class inherits from. Then you can include that instead of the declaration of the real class.
2) Pimpl - a class holds an opaque pointer to its real data, solving the problem of having to include declarations for the types of member variables.
I know this is going to sound dodgy, but have you considered holding a global reference to the initialized Game class?
I know globals are evil and so on and so forth, and I'm sure lots of people are going to rage, but in my personal experience I have succumb to Singletonitis with the Game class (among others) and found that sometimes it just simply isn't necessary.
The biggest question you need to ask yourself is "Who are you trying to protect your Game object from? and is there any reason why you need to request an instance each time you need the game class? I'm pretty sure that if your Game object wasn't initialized, you wouldn't be doing much else in your engine anyway.
Hope this might help you think about things in a different way, even though it's not answering your question directly.
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.
If i have a class name app and a class name manager. I want to create inside manager class an app class, I've seen two options but I didn't understand the difference.
choice 1:
//.....
class app; //writing this line outside the declaration of the func
class manager{
//..
private:
app *a;
//...
}
or choice 2:
class manager{
//..
private:
app *a;
//..
}
I think you're talking about forward declaration. If so, then read this:
C++ INCLUDE Rule : Use forward declaration when possible
Read also this FAQ:
[39.12] What special considerations are needed when forward declarations are used with member objects?
The class app; outside your class manager { ... } is a forward declaration. It tells the compiler, "app is a class. I'm not going to tell you what it looks like, but trust me, it is."
Think of your compiler as only knowing about this particular file (which I am assuming is a .h file) when it compiles. You have said that your member class includes a pointer to an "app". "What the heck is an app?" the compiler wants to know. Without the forward declaration (or perhaps an #include app.h or something similar), it doesn't know, and will fail to compile. By saying at the top, class app;, it knows that app is a class. That's all it needs to know to allocate the space for a pointer to it in your member class.
Look, your "choice 2" isn't valid C++. Who knows what was on your mind... Maybe you wanted to write something like this:
class manager {
//..
private:
class app *a;
//..
}
In this case we define pointer to app class, which is unknown here. This can be used instead of #include "app.h", because all pointers are of the same size and you can define a pointer without defining that app class. Your first example does the same thing, but allows you to omit class word in all subsequent definitions of pointers to it.
The first example includes a forward declaration of the class app so that you can declare pointers to it in later code. The second example doesn't mention app at all before you attempt to use it, so the compiler will not accept it. The compiler needs to know what the name app refers to before you can use it to declare additional things.
Since you're only declaring a pointer, you don't yet need to have a full declaration of app. But in order for your program to fully compile and link, you'll need to define app eventually. Possibly within the same file, or possibly in some other file. But somewhere before you attempt to create an instance of that class or use any of its member variables and functions.