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.
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.
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.
Currently, I'm writing a project for fun and faced next problem.Let's suppose I'm creating class Bank and I want to define classes LoginController and Departure
class Bank{
class LoginController{
//some implemantation
}
class Departure{
//some departure
}
}
To avoid making huge declaration of Bank inside Bank.h I want to define them in separate files
//Bank.h
#include "LoginController.h"
#include "Departure"
class Bank{
class LoginController;
class Departure;
LoginController controller;
Departure departure;
...
}
//LoginController.h
class Bank; //forward declaration
class Bank::LoginController{
bool getAccess(Bank::Departure);
}
//Departure.h
//Departure depends on Bank class aswell
class Bank; //forward declartion
class Bank::Departure{...}
This code wont compile with huge stack trace.It can be solved with one big Bank.cpp and writing it all there, however, i don't want to make one huge file.
I assume this is a bad design problem, however, i'm still interested if it possible to implement this class as I wanted.Even if I define LoginController && Departure structure inside Bank i want separate cpp files for each class, however, header guard will close access to it after including it to one of cpp files.The best solution i can see is defining all in one header but not inside each other.
And one more question.Is it possible to define 1 header file with all includes like
#ifndef HeaderFile
#define HeaderFile
#include <iostream>
#include <memory>
....
#endif
From the previous question, i understand that this will open only for one file, therefore do we need to provide each file with needed headers. Including the same header to different files seems expensive.
You can put the #include directives inside the Bank class.
Bank.h
class Bank {
#include "LoginController.h"
#include "Departure.h"
// Bank implementation
}
LoginController.h
class LoginController {
// some implementation
}
Departure.h
class Departure {
// some implementation
}
I have three classes.
first class:
#ifndef C_LINKED_LIST_H
#define C_LINKED_LIST_H
class CLinkedList {
private:
//removed code for brevity
public:
// removed code for brevity
};
#endif
second class:
#ifndef C_SSF_FOLDER_CONTAINER_H
#define C_SSF_FOLDER_CONTAINER_H
#include "C_SSF_Folder.h"
#include "CLinkedList.h"
class C_SSF_Folder_Container {
private:
// removed code for brevity
public:
int Add_Folder(C_SSF_Folder *_pcl_SSF_Folder);
C_SSF_Folder *Get_Folder(int _i_Index);
C_SSF_Folder *Get_Folder(char *_pch_Name);
//^-----errors
};
#endif C_SSF_FOLDER_CONTAINER_H
my third class
#ifndef C_SSF_FOLDER_H
#define C_SSF_FOLDER_H
#include <windows.h>
#include <fstream>
#include "C_SSF_Folder_Container.h"
using namespace std;
class C_SSF_Folder {
public:
private:
C_SSF_Folder_Container cl_SSFFC_Folder_Container;
public:
};
#endif
my third class C_SSF_Folder.
I am including "C_SSF_Folder_Container.h"
and declaring a C_SSF_Folder_Container container.
Before declaring the variable it compiles fine. After I declare it
I get syntax errors in my C_SSF_Folder_Container
Severity Code Description Project File Line Suppression State
Error C2061 syntax error: identifier 'C_SSF_Folder' CSSFileSystem\projects\cssfilesystem\cssfilesystem\c_ssf_folder_container.h 16
Error C2061 syntax error: identifier 'C_SSF_Folder' CSSFileSystem \projects\cssfilesystem\cssfilesystem\c_ssf_folder_container.h 19
As I myself look into it I think there is a problem because my C_SSF_Folder is including C_SSF_Folder_Container.
and C_SSF_Folder_Container is including C_SSF_Folder
but the defines should take care of it? Other than that I have no clue what's the problem.
Everything is typed correctly.
You've got a circular #include -- C_SSF_Folder_Container.h #includes C_SSF_Folder.h and C_SSF_Folder.h #includes C_SSF_Folder_Container.h.
This would cause an infinite regress (and a compiler crash) except that you've got the #ifndef/#define guards at the top of your files (as you should); and because of them, instead what you get is that one of those two .h files can't see the other one, and that's why you get those errors.
The only way to fix the problem is to break the circle by deleting one of the two #includes that comprise it. I suggest deleting the #include "C_SSF_Folder.h" from C_SSF_Folder_Container.h and using a forward declaration (e.g. class C_SSF_Folder; instead.
C_SSF_Folder.h and C_SSD_Folder_Container.h are including each other(Circular Dependency).
When the compiler compiles C_SSF_Folder_Container object, it needs to create a C_SSF_Folder object as its field, however, the compiler needs to know the size of C_SSF_Folder object, so it reaches C_SSF_Folder object and tries to construct it. Here is the problem, when the compiler is constructing C_SSF_Folder object, the object has a C_SSF_Folder_Container object as its field, which is a typical chicken and egg question, both files depends on each other in order to compile.
So the correct way to do it is to use a forward declaration to break the circular dependency(including each other).
In your C_SSF_Folder.h, make a forward declaration of C_SSF_Folder_Container.
#include <windows.h>
#include <fstream>
using namespace std;
class C_SSF_Folder_Container;
class C_SSF_Folder {
public:
private:
C_SSF_Folder_Container cl_SSFFC_Folder_Container;
public:
};
#endif
Finally, include C_SSF_Folder_Container.h in your C_SSF_Folder.cpp.
You can also learn more in the following links:
Circular Dependency (Wiki):
https://en.wikipedia.org/wiki/Circular_dependency
Forward Declaration by Scott Langham
What are forward declarations in C++?
I have a dialog window settings that I want to display all values from my breadData object, and to do so I want to have settings inherit breadData's protected members. I try to forward declare breadData, but I'm getting a couple errors in my code.
/home/--/breadPull/prj/settings.h:14: error: invalid use of incomplete type 'struct breadData'
/home/--/breadPull/prj/resultwnd.h:7: error: forward declaration of 'struct breadData'
For one, breadData is not a struct, why does the compiler think breadData is a struct? Secondly I don't understand what the second line is trying to say. My only guess is because there are a lot of circular dependencies in my program. Here's the relevant code:
settings.h
#include <QDialog>
#include "breaddata.h"
class breadData;
namespace Ui {
class Settings;
}
class Settings : public QDialog, public breadData
{
Q_OBJECT
//.....
breadData.h
#include <vector>
#include <string>
#include <QtWidgets>
#include <QMainWindow>
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "resultwnd.h"
#include "settings.h"
class MainWindow;
class resultWnd;
class breadData
{
public:
breadData(std::string);
~breadData();
//read in data file that provides all information
bool readData();
//.......
resultWnd.h
include <QGroupBox>
#include "breaddata.h"
class breadData;
namespace Ui {
class resultWnd;
}
class resultWnd : public QGroupBox
//.....
You have a circular dependency. breaddata.h includes settings.h before declaring breaddata. settings.h requires the declaration of breaddata for the inheritance.
Thus the file the preprocessor creates when compiling a file that includes breaddata first looks like this (indentation to visualize the recursive insertion of included header files):
<content of breaddata.h>:
<content of vector, string, QtWidget, QMainWindow, mainwindow.h and ui_mainwindow.h>
...
<content of resultWnd>:
...
class breaddata; //forward declaration mentioned in the error message
...
<content of settings.h>:
...
class Settings : public QDialog, public breadData //DANG!
...
class breaddata { ... //too late
Summarized:
class breaddata; //forward declaration mentioned in the error message
...
class Settings : public QDialog, public breadData //DANG!
...
class breaddata { ... //too late
The solution here is to avoid the includes in breaddata.h, especially settings.h. If necessary, forward-declare Settings. The rule of thumb is to include in headers only if you must, and forward-declare whenever you can.
Your problem is that you have an incomplete understanding of the following:
The precompiler
The difference between declarations and definitions and purpose of using the former.
The purpose and use of namespaces
Without knowing more about your code than what you've shown, the following should solve your problem:
settings.h
#ifndef SETTINGS_H
#define SETTINGS_H
// Your code as above
#endif
breaddata.h
#ifndef BREADDATA_H
#define BREADDATA_H
// Your code as above
#endif
resultWnd.h
#ifndef RESULTWND_H
#define RESULTWND_H
// Your code as above
#endif
I suspect that this will not solve your problem entirely though. Based on your second error message, I suspect you have left important lines of code out of your question so nobody will be able to give you a definitive answer to solve your problem.
I suggest you edit the code in your question to include all lines that contain the breadData, Settings and resultWnd
It is possible to solve this, we just need to see how the three classes are bound together so we can help you untangle them.
The reason the compiler thinks you're using a struct is purely historical. The class keyword was introduced in C++ with the intention to replace the struct. Previously, in C, only the struct keyword exists. As far as I know, the only difference between structs and classes is the default access level. classes default to private while structs default to public. Otherwise, they have identical usage.