Class redefinition problems using forward declarations - c++

NOTE: Reupload of a question wrongly marked as duplicate
I'm working with Ogre, but my question resides specifically within namespaces.
I haven't been able to find an answer that helps me here.
I'm trying to forward declare Ogre::xyz classes within my header file for a CameraController.
This is the header file
class Ogre;
class Ogre::SceneNode;
class Ogre::SceneManager;
class CameraController
{
private:
Ogre::SceneNode* camNode;
Ogre::SceneManager* scnMgr;
};
This is the cpp file
#include "CameraController.h"
#include <OgreSceneManager.h>
#include <OgreSceneNode.h>
... definitions of functions.
What's the correct way to achieve what I'm trying to do here, in avoiding including unneeded header files within the CameraController.h file
ATTEMPT TO FIX
I attempted the redefinition as marked in a 'duplicate' that talked about declaring classes in namespaces:
namespace Ogre
{
class SceneManager;
class SceneNode;
class Camera;
class Viewport;
class Real;
}
class CameraController
{
private:
Ogre::Real getAspectRatio();
private:
Ogre::SceneNode* camNode;
Ogre::Camera* camera;
Ogre::Viewport* viewPort;
Ogre::SceneManager* scnMgr;
};
EDIT
So the error I am having now is that the classes that I forward declare within the Ogre namespace are being redefined by the headers that I include in the .cpp file

The capitalization of ViewPort and Viewport in the forward declaration is different. C++ would see them as different values.

Related

Handling circular dependencies in C++ [duplicate]

This question already has answers here:
Resolve build errors due to circular dependency amongst classes
(12 answers)
Closed 2 years ago.
So, I know that there are many questions on stack overflow out there that are trying to handle circular dependencies. But none of those could really answer my question, if it is possible to have two classes know each other, and, more importantly, access information from each other. So, basically, I have read that you could use forward decleration, but with forward decleration, I couldn't access any fields. Maybe I should also add that I am really new to C++.But enough talking, let's get to an example:
Let's say we have a class called Scene and a class called EntityBase, which are defined as following:
EntityBase.h
#pragma once
#include <string>
#include "Scene.h"
class EntityBase
{
public:
std::string entityId;
Scene scene;
EntityBase(std::string entityId);
/*
This method will be called when this object is added to the scene
*/
void onAddedToScene(Scene* scene);
/*
This method will be called when this object is removed from the scene
*/
void onRemovedFromScene(Scene* scene);
};
Scene.h
#pragma once
#include <vector>
#include <string>
#include "EntityBase.h"
class Scene
{
public:
std::vector<EntityBase> entities;
std::string name;
Scene(std::string name);
void addToScene(EntityBase& entityBase);
};
The question arises,
How can I print out the name of Scene(and use every method of Scene) while EntityBase can fully access Scene too?
So, I'd really appreciate if you'd tell how to do this, because I will probably need to access every field and/or method later.
Since the C++17 standard you don't need the full EntityBase class definition for the Scene class, only a forward declaration:
#pragma once
#include <vector>
#include <string>
class EntityBase; // Forward declaration
class Scene
{
public:
std::vector<EntityBase> entities;
std::string name;
Scene(std::string name);
void addToScene(EntityBase& entityBase);
};
You of course need to include EntityBase.h anywhere where the entities vector is used, most notable in the Scene.cpp source file.
Since EntityBase is using an actual instance of Scene you can't do the same with that class and the EntityBase.h header file. Here you must include the Scene.h header file.
If you build targeting an older C++ standard (C++14 or earlier) then you must have the full definition of the EntityBase class for the vector.
As a possible workaround either make entities a vector of pointers to EntityBase; Or make EntityBase::scene a pointer and use forward declaration in the EntityBase.h header file instead. Or a combination of both.

C++ forward declarations with multiple classes, derived class

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.

C++ circular include

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.

Defining a class method in another file

I know how to define a class method inside of the same file with which the class is in.
For example:
class Robot
{public:
int location;
void Moves(); //Class method to be defined
}
void Robot::Moves()
{//Method definition here }
I do NOT know hot to define a class outside of the file in which the class is in. I tried creating a .hpp file and defining a class method inside of it, but my compiler signified that it could not load a class definition from a file other than the one the class was created in, or it would be as though I was placing a function's definition before the include directives.
Please note: The original class file is also in a .hpp file, as I have yet to learn how to use .cpp files other than the main one.
This is done using C++/Win32.
Create a .cpp file along these guidelines
Include your class header file in your .cpp file
Include all necessary headers you would use in main.cpp
use the scope operator for your class
#include <iostream>
#include "foo.hpp"
foo::foo()
{
// code here
}
void foo::OtherFunc()
{
// other stuff here
}
Just put your definition in a .cpp file and link it with your application.
Robot.hpp:
class Robot
{public:
int location;
void Moves(); //Class method to be defined
}
Robot.cpp:
#include "Robot.hpp"
void Robot::Moves()
{//Method definition here }

Dealing with circular dependency on inheritance

I'm gonna go C++ über n00b on this one and ask how is the best way to deal with a circular dependency when you have inheritance.
The set is simple: Scene class extends Actor; Scene has a pointer to a vector of Actors; Actor has a pointer for (parent) Scene.
As for include files I got:
Scene.h:
#include <string>
#include <vector>
using namespace std;
#ifndef __Scene_h__
#define __Scene_h__
#include "Actor.h"
namespace myns
{
// class Actor;
class Scene;
}
namespace myns
{
class Scene: public myns::Actor
{
/* private class attributes... */
public:
/* public class attributes... */
std::vector<myns::Actor*> actors;
Scene(/* arguments */);
/* public class methods... */
};
}
#endif
Actor.h
#include <string>
#include <vector>
using namespace std;
#ifndef __Actor_h__
#define __Actor_h__
#include "Scene.h"
namespace myns
{
// class Scene;
class Actor;
}
namespace myns
{
class Actor
{
/* private class attributes... */
public:
/* public class attributes... */
myns::Scene* scene;
Actor();
Actor(/* arguments */);
/* public class methods... */
};
}
#endif
But this gives me alot of C2504 errors/base class undefined on Visual Studio 2010.
If I comment the Scene.h include on the Actor.h and uncomment the forward declaration of Scene on Actor.h it works, but then, in my app, if I want to include only the Actor.h on a particular piece of code, it will not work. How can I put this to work while maintaining the inclusion independence for Actor.h - including Actor.h without the need of previously manually including Scene.h?
What is wrong with my class definitions and how is the best way to deal with this circular dependency?
Shouldn't the #ifndef directives prevent this inclusion problem?
Thanks in advance.
but then, in my app, if I want to include only the Actor.h on a particular piece of code, it will not work
What you need to do is in the .cpp file where you need to use define the Actor class you must include both Actor.h and Scene.h. That way the forward declaration will be resolved and everything should work.
As an aside, you should move your #ifndef and #define right to the top of the file, before the includes. Also, having a using in a header file is bad practice because other files that include your header might not work properly. It should be ok to put it inside your namespace myns { ... } though.
Is a Scene really a type of Actor?
If it is, Actors probably shouldn't know about Scenes. Base classes shouldn't usually know about their derived classes.
Where is the Liskov Substitution Principle here? What action do you perform on an Actor that would be polymorphically performed differently by a Scene.
In any case, Scene derives from Actor so must include its base class. But in Actor.h if you really do need the Scene class it must be a forward declaration only.
In the compilation units (the .cpp files) you might include both headers if required.