I can't solve this circular dependency problem; always getting this error:
"invalid use of incomplete type struct GemsGame"
I don't know why the compiler doesn't know the declaration of GemsGame even if I included gemsgame.h
Both classes depend on each other (GemsGame store a vector of GemElements, and GemElements need to access this same vector)
Here is partial code of GEMELEMENT.H:
#ifndef GEMELEMENT_H_INCLUDED
#define GEMELEMENT_H_INCLUDED
#include "GemsGame.h"
class GemsGame;
class GemElement {
private:
GemsGame* _gemsGame;
public:
GemElement{
_gemsGame = application.getCurrentGame();
_gemsGame->getGemsVector();
}
};
#endif // GEMELEMENT_H_INCLUDED
...and of GEMSGAME.H:
#ifndef GEMSGAME_H_INCLUDED
#define GEMSGAME_H_INCLUDED
#include "GemElement.h"
class GemsGame {
private:
vector< vector<GemElement*> > _gemsVector;
public:
GemsGame() {
...
}
vector< vector<GemElement*> > getGemsVector() {
return _gemsVector;
}
}
#endif // GEMSGAME_H_INCLUDED
Remove the #include directives, you already have the classes forward declared.
If your class A needs, in its definition, to know something about the particulars of class B, then you need to include class B's header. If class A only needs to know that class B exists, such as when class A only holds a pointer to class B instances, then it's enough to forward-declare, and in that case an #include is not needed.
If you deference the pointer and the function is inline you will need the full type. If you create a cpp file for the implementation you can avoid the circular dependecy (since neither of the class will need to include each others .h in their headers)
Something like this:
your header:
#ifndef GEMELEMENT_H_INCLUDED
#define GEMELEMENT_H_INCLUDED
class GemsGame;
class GemElement {
private:
GemsGame* _gemsGame;
public:
GemElement();
};
#endif // GEMELEMENT_H_INCLUDED
your cpp:
#include "GenGame.h"
GenElement::GenElement()
{
_gemsGame = application.getCurrentGame();
_gemsGame->getGemsVector();
}
Two ways out:
Keep the dependent classes in the same H-file
Turn dependency into abstract interfaces: GemElement implementing IGemElement and expecting for IGemsGame, and GemsGame implementing IGemsGame and containing a vector of IGemElement pointers.
Look at the top answer of this topic: When can I use a forward declaration?
He really explains everything you need to know about forward declarations and what you can and cannot do with classes that you forward declare.
It looks like you are using a forward declaration of a class and then trying to declare it as a member of a different class. This fails because using a forward declaration makes it an incomplete type.
Related
Currently I have 3 classes, set up like this:
World.h
include "WorldObject.h"
class WorldObject;
class TextObject; // when this is added, compiles fine, but tobj is incomplete when accessed
//(world->tobj->function()). if #include "TextObject.h" is added, numerous errors occur within TextObject.h
class World {
public:
WorldObject* wobj; // works fine
TextObject* tobj; //trying to get this to be functional
};
WorldObject.h
#include "World.h"
class World;
class WorldObject {
public:
WorldObject(World* world){...} // works fine, world can be accessed from world objects
};
TextObject.h
#include "WorldObject.h"
#include "World.h"
class TextObject : WorldObject {
public:
TextObject(World* world) : WorldObject(w){...};
};
How can I use forward declaration so that tobj will be accessible from World.h, as obj is, with no errors? I am also using #pragma once at the beginning of each class. I have attempted to add "class World" to TextObject.h and "class TextObject" to World.h, but none of the seemingly standard procedures are working. Any suggestions?
#include <WorldObject.h> in your .cpp file rather than your header and you can access it from there.
Your header includes are causing circular dependencies, which you avoid through forward declarations.
I would like to split a class implementation into three parts, to avoid that users need to deal with the implementation details, e.g., the libaries that I use to implement the functionality:
impl.cpp
#include <api.h>
#include <impl.h>
Class::Class() {
init();
}
Class::init() {
myData = SomeLibrary::Type(42);
}
Class::doSomething() {
myData.doSomething();
}
impl.h
#include <somelibrary.h>
class Class {
public:
Class();
init();
doSomething();
private:
SomeLibary::Type myData;
}
api.h
class Class {
Class();
doSomething();
}
The problem is, that I am not allowed to redefine headers for the class definition. This does not work when I define Class() and doSomething() only in api.h, either.
A possible option is to define api.h and do not use it in the project at all, but install it (and do not install impl.h).
The obvious drawback is, that I need to make sure, that the common methods in api.h and impl.h always have the same signature, otherwise programs using the library will get linker errors, that I cannot predict when compiling the library.
But would this approach work at all, or will I get other problems (e.g. wrong pointers to class members or similar issues), because the obj file does not match the header?
The short answer is "No!"
The reason: any/all 'client' projects that need to use your Class class have to have the full declaration of that class, in order that the compiler can properly determine such things as offsets for member variables.
The use of private members is fine - client programs won't be able to change them - as is your current implementation, where only the briefest outlines of member functions are provided in the header, with all actual definitions in your (private) source file.
A possible way around this is to declare a pointer to a nested class in Class, where this nested class is simply declared in the shared header: class NestedClass and then you can do what you like with that nested class pointer in your implementation. You would generally make the nested class pointer a private member; also, as its definition is not given in the shared header, any attempt by a 'client' project to access that class (other than as a pointer) will be a compiler error.
Here's a possible code breakdown (maybe not error-free, yet, as it's a quick type-up):
// impl.h
struct MyInternal; // An 'opaque' structure - the definition is For Your Eyes Only
class Class {
public:
Class();
init();
doSomething();
private:
MyInternal* hidden; // CLient never needs to access this! Compiler error if attempted.
}
// impl.cpp
#include <api.h>
#include <impl.h>
struct MyInternal {
SomeLibrary::Type myData;
};
Class::Class() {
init();
}
Class::init() {
hidden = new MyInternal; // MUCH BETTER TO USE unique_ptr, or some other STL.
hidden->myData = SomeLibrary::Type(42);
}
Class::doSomething() {
hidden->myData.doSomething();
}
NOTE: As I hinted in a code comment, it would be better code to use std::unique_ptr<MyInternal> hidden. However, this would require you to give explicit definitions in your Class for the destructor, assignment operator and others (move operator? copy constructor?), as these will need access to the full definition of the MyInternal struct.
The private implementation (PIMPL) idiom can help you out here. It will probably result in 2 header and 2 source files instead of 2 and 1. Have a silly example I haven't actually tried to compile:
api.h
#pragma once
#include <memory>
struct foo_impl;
struct foo {
int do_something(int argument);
private:
std::unique_ptr<foo_impl> impl;
}
api.c
#include "api.h"
#include "impl.h"
int foo::do_something(int a) { return impl->do_something(); }
impl.h
#pragma once
#include <iostream>
struct foo_impl {
foo_impl();
~foo_impl();
int do_something(int);
int initialize_b();
private:
int b;
};
impl.c
#include <iostream>
foo_impl::foo_impl() : b(initialize_b()} { }
foo_impl::~foo_impl() = default;
int foo_impl::do_something(int a) { return a+b++; }
int foo_impl::initialize_b() { ... }
foo_impl can have whatever methods it needs, as foo's header (the API) is all the user will see. All the compiler needs to compile foo is the knowledge that there is a pointer as a data member so it can size foo correctly.
Apologies if you have seen this question before however it has yet to be answered, essentially in my code I have two structs, defined in separate headers and used globally throughout the project. I simply wish to use both structs (which again, are defined in two separate headers) in other cpp files than just the ones that the header file belongs to.
Here is some sample code which I have tested:
class1.h
#include "class2.h"
#include <vector>
#include <string>
struct trans1{
string name;
};
class class1 {
private:
vector <trans2> t2;
public:
class1();
};
class2.h
#include "class1.h"
#include <vector>
#include <string>
struct trans2{
string type;
};
class class2{
private:
vector <trans1> t1;
public:
class2();
};
errorlog:
In file included from class1.h:3:0,
from class1.cpp:1:
class2.h:21:13: error: 'trans1' was not declared in this scope
vector <trans1> t1;
^
class2.h:21:19: error: template argument 1 is invalid
vector <trans1> t1;
^
class2.h:21:19: error: template argument 2 is invalid
I understand that this is ridiculous code in a real world application however this is the simplest way I could demonstrate.
It is worth noting that if I simply comment out the declaration of vector t1 or t2 under 'private:' the code compiles without fail. It is just the fact I am using a second struct.
Any help anyone? Thanks.
Simply forward-declare the classes that will be used. Put all implementation code into a cpp file, not inline in the header.
Make the vector private. This way no file that includes the header can force code generation against an incomplete class.
you can try to forward declare trans1 in class2.h and trans2 in class1.h like this:
class2.h :
// includes
struct trans1;
// rest of your code
the same thing (but with trans2) in class1.h
Don't forget to add Include guards in your code!
edit: and yes, you need to change your vectors to store pointers, otherwise it won't link
You need to put the "trans" structs in their own header file(s) and include them in your class header files.
You could forward declare them, but this would require changing your vector to use pointers. (In that case I would recommend std::vector<std::unique_ptr<trans>>). This could be appropriate if your structs are big and complex.
The main advantage of the forward-declaration approach is to reduce compile times. However if the structs are really so simple as in your example, I wouldn't bother with the extra overhead of using pointers here.
If You were to do this in single .cpp file, the solution would be trivial:
struct trans1 { ... };
struct trans2 { ... };
class class1 { ... };
class class2 { .... };
Now you just need to rearrange the code to get this result in every translation unit. (the order of classes/structs in the file is important)
I'm trying to refactor my code so that I use forward declarations instead of including lots of headers. I'm new to this and have a question regarding boost::shared_ptr.
Say I have the following interface:
#ifndef I_STARTER_H_
#define I_STARTER_H_
#include <boost/shared_ptr.hpp>
class IStarter
{
public:
virtual ~IStarter() {};
virtual operator()() = 0;
};
typedef boost::shared_ptr<IStarter> IStarterPtr;
#endif
I then have a function in another class which takes an IStarterPtr object as argument, say:
virtual void addStarter(IStarterPtr starter)
{
_starter = starter;
}
...
IStarterPtr _starter;
how do I forward declare IStarterPtr without including IStarter.h?
I'm using C++98 if that is of relevance.
Shared pointers work with forward declared types as long as you dont call * or -> on them so it should work to simply write :-
class IStarter;
typedef boost::shared_ptr<IStarter> IStarterPtr;
You need to include <boost/shared_ptr.hpp> of course
Though it would add a header file, you could put that in a separate header file :
#include <boost/shared_ptr.hpp>
class IStarter;
typedef boost::shared_ptr<IStarter> IStarterPtr;
and then include it both in IStarter.h and in your other header, avoiding code duplication (though it's quite small in this case).
There might be better solutions though.
You can't forward declare typedefs in C++98 so what I usually do in this case is pull out the typedefs I need an put them into a types.h file, or something similar. That way the common type code is still separated from the definition of the class itself.
There is a way but you need to include the boost header in your file :
#include <boost/shared_ptr.hpp>
class IStarter;
typedef boost::shared_ptr<IStarter> IStarterPtr;
// ...
virtual void addStarter(IStarterPtr starter)
{
_starter = starter;
}
// ...
IStarterPtr _starter;
I'm looking to have a hierarchical class structure in which a level of controller 'parent' classes are responsible for creating/directing a number of 'child' classes. The parent class should be able to reference each child it creates directly, and each child should be able to reference its parent (and, assuming this child is not also a parent of more classes, only its parent) directly. This allows for the referencing of siblings through the parent. I've found this paradigm to be useful in JIT compilation languages like Java and C#, but C++ presents a unique problem...
My first attempt to implement this paradigm was as follows:
Parent Class TreeRoot.h
#ifndef __CCPP_SCENE_H__
#define __CCPP_SCENE_H__
#include "ChildA.h"
#include "ChildB.h"
class TreeRoot :
{
private:
ChildA* a;
ChildB* b;
public:
//member getters
ChildA* getA();
ChildB* getB();
};
#endif // __CCPP_SCENE_H__
Child class ChildA.h
#ifndef CHILDA_H_
#define CHILDA_H_
#include "TreeRoot.h"
class ChildA
{
private:
TreeRoot* rootScene;
public:
ChildA(TreeRoot*);
~ChildA(void);
TreeRoot* getRootScene();
void setRootScene(TreeRoot*);
};
#endif /*CHILDA_H_*/
Child class ChildB.h
#ifndef CHILDB_H_
#define CHILDB_H_
#include "TreeRoot.h"
class ChildB
{
private:
TreeRoot* rootScene;
public:
ChildB(TreeRoot*);
~ChildB(void);
TreeRoot* getRootScene();
void setRootScene(TreeRoot*);
};
#endif /*CHILDB_H_*/
Now of course that wouldn't compile because of the circular include (TreeRoot.h includes ChildA.h and ChildB.h, which both include TreeRoot.h etc) So I tried using forward declaration instead:
Parent Class TreeRoot.h
#ifndef __CCPP_SCENE_H__
#define __CCPP_SCENE_H__
#include "ChildA.h"
#include "ChildB.h"
class TreeRoot :
{
private:
ChildA* a;
ChildB* b;
public:
//member getters
ChildA* getA();
ChildB* getB();
};
#endif // __CCPP_SCENE_H__
Child class ChildA.h
#ifndef CHILDA_H_
#define CHILDA_H_
//#include "TreeRoot.h" //can't use; circular include!
class TreeRoot;
class ChildA
{
private:
TreeRoot* rootScene;
public:
ChildA(TreeRoot*);
~ChildA(void);
TreeRoot* getRootScene();
void setRootScene(TreeRoot*);
};
#endif /*CHILDA_H_*/
Child class ChildB.h
#ifndef CHILDB_H_
#define CHILDB_H_
//#include "TreeRoot.h" //can't use; circular include!
class TreeRoot;
class ChildB
{
private:
TreeRoot* rootScene;
public:
ChildB(TreeRoot*);
~ChildB(void);
TreeRoot* getRootScene();
void setRootScene(TreeRoot*);
};
#endif /*CHILDB_H_*/
that implementation almost works in that I can successfully broadcast messages to the child objects and perform callbacks from the child objects to the parent class as follows:
TreeRoot.cpp
...
a->someChildMethod();
a->getRootScene()->someParentMethod();
However when I try the following:
ChildA.cpp
...
rootScene->someParentMethod(); //ERROR C2027: use of undefined type TreeRoot
I get an undefined type error. This makes sense since using forward declaration as above doesn't inform the compiler of what TreeRoot actually is. The question then is how can I enable calls from the child objects like the rootScene->someParentMethod() call above? Perhaps some use of generic types via templates would make the compiler happy and provide the functionality I'm looking for?
thanks,
CCJ
Use a forward declaration in all your .h files. You can do this since you're only storing pointers as class members so you don't need the full class declaration.
Then, in all your corresponding .cpp files, #include the header files for the classes you need.
So, in TreeRoot.h you forward declare ChildA and ChildB. In TreeRoot.cpp, you #include ChildA.h and ChildB.h.
Rinse and repeat for your 2 other classes.
Take note that this will solve your current problem, but this design seems flaky at best.
You could try including the 'TreeRoot.h' in the ChildA and ChildB files. I would also suggest using Polymorphism and create a parent class, which A and B inherit from, for shared behaviour.
This doesn't involve fiddling with the header files, but my suggestion: Either make all your nodes the same class (enables more flexibility [what if you decide you want to make a tree into a subtree of another tree? you'd have to change the class of the root node from the first tree into the child class], and, at least in my mind, makes more sense/seems more elegant/would lessen the amount of and/or simplify the code you'd have to write), or use a superclass for both parent and child node classes (as ATaylor suggests), though I feel that would only be a better solution if your parent and child nodes have a lot of differing functionality beyond that which they would require to form the tree structure.
In ChildA.cpp file you have to include the parent header as
#include "TreeRoot.h"