I have an error in my code. All the forums says "in this situation, use Forward Declaration". I tried this and it don't work.
the error is C2079 Credit::mainMenu use a class of MainMenu not declared (translated from french)
I modified the classe to be specific to the question.
main.cpp
#include <SFML/Graphics.hpp>
#include "Menu.h"
#include "credit.h"
#include "mainmenu.h"
MainMenu *mainMenu = new MainMenu();//works here
int main(){
return 0;
}
credit.h
#ifndef DEF_CREDIT
#define DEF_CREDIT
#include <SFML/Graphics.hpp>
#include "Menu.h"
class MainMenu;
class Credit : public Menu
{
private:
MainMenu mainMenu = MainMenu();//DON'T WORK HERE
};
#endif
mainmenu.h
#ifndef DEF_MAINMENU
#define DEF_MAINMENU
#include <SFML/Graphics.hpp>
#include "Menu.h"
#include "credit.h"
class MainMenu :public Menu
{
private:
Credit credit = Credit();//work
};
#endif
Fist i load main.cpp
after the credit.h (there is a credit.hpp but i don't use the variable now)
after the mainmenu.h (there is also a mainmenu.hpp, i don't use variable now)
tip: the Menu class isn't including any of those class
I can send you the complete code if you want
Thanks in advence!
This issue is know as circular dependency. Long story short, two objects should never have another as its subobject.
Instead you have two options. One is to have one point to another
class Credit : public Menu
{
private:
MainMenu* mainMenu;
};
Or, you could have a manager of sorts, where only the manager is aware of both objects, and let them interact through the manager
class Manager
{
private:
Credit credit;
MainMenu mainMenu;
};
For the technical reason why you can't have a member of a declared but not defined type is because it is a incomplete type, and you can't have an object of incomplete type.
Related
I want to create some objects that can delegate some work to its nested subobjects, but it pushes me into the circular dependency issues. Using of #ifndef directive works fine if I have only two classes (ClassA and ClassB), but this pattern doesn't work when ClassC is added. Is it possible to achieve such type of structure as shown in the code below and don't get an "undefined type" errors?
ClassA.h
#pragma once
#include "CoreMinimal.h"
#include "ClassB.h"
class UClassB;
#include ClassA.generated.h
UCLASS()
class PROJ_API UClassA : public UObject
{
GENERATED_BODY()
UPROPERTY()
UClassB* ObjB;
public:
void DoDelegation()
{
auto* ThisInstance = this;
ObjB = NewObject<UClassB>();
ObjB->DoWorkClassB(ThisInstance);
}
}
ClassB.h
#pragma once
#include "CoreMinimal.h"
//works nice
#ifndef CLASSA_H
#define CLASSA_H
#include "ClassA.h"
class UClassA;
#endif
//trying to use similar pattern which works with ClassA.h and ClassB.h
#include "ClassC.h"
class UClassC;
#include ClassB.generated.h
UCLASS()
class PROJ_API UClassB : public UObject
{
GENERATED_BODY()
UPROPERTY()
UClassC* ObjC;
public:
void DoDelegation()
{
auto* ThisInstance = this;
ObjC = NewObject<UClassC>();
ObjC->DoWorkClassC(ThisInstance);
}
void DoWorkClassB(UClassA* &ObjectClassA)
{
// do some stuff with ObjectClassA
}
}
ClassC.h
#pragma once
#include "CoreMinimal.h"
//trying to use similar pattern which works with ClassA.h and ClassB.h
//got "undefined type" error
#ifndef CLASSB_H
#define CLASSB_H
#include "ClassB.h"
class UClassB;
#endif
#include ClassC.generated.h
UCLASS()
class PROJ_API UClassC : public UObject
{
GENERATED_BODY()
public:
void DoWorkClassC(UClassB* &ObjectClassB)
{
// do some stuff with ObjectClassB
}
}
creating classes that refer to each other
Is it possible to achieve such type of structure as shown in the code below and don't get an "undefined type" errors?
Certainly. Referring to an object (with a pointer for example) of some class only requires declaration of the other class, not definition.
Simple solution is to declare both classes before defining either of them.
It's still not fully clear for me, but at least i understood why forward declaration wasn't worked for the first time. Inline implementation of methods that do something with such referencing classes is strictly not recommended. It compiles well If function is implemented in cpp.
I've been programming a Monopoly game for a final project. So I thought I was on a roll, and that I had everything figured out with my psuedocode. But, it seems I forgot how to deal with includes properly, I know that is the issue since I was able to refine it to that point, but I'm not sure how to fix it.
In this super stripped down version of my code I have three .h files "Space.h" which is an abstract/virtual class which has to be inherited by a variety of different spaces that can appear on a typical Monopoly board: properties, jail, taxes, Chance, Community Chest, etc. The function that has to be inherited is run(Player&) which is what is "run" when you land on that particular space on the board, all functions that use run use a player passed by argument.
#pragma once
#include <string>
#include "Player.h"
class Space
{
public:
virtual void run(Player&) = 0;
};
My second .h file is the "Property.h" this inherits from Space
#pragma once
#include "Space.h"
class Property : Space
{
public:
void run(Player&) override;
int i{ 0 };
};
Lastly I have the "Player.h" which has two variables a name and a vector of properties it owns.
#pragma once
#include <string>
#include <vector>
#include "Property.h"
class Player
{
public:
std::string name{ "foo" };
void addProperty(Property p);
private:
std::vector <Property> ownedProperties;
};
Here's a very basic Property implementation
#include "Property.h"
#include <iostream>
void Property::run(Player & p)
{
std::cout << p.name;
}
Player implementation
#include "Player.h"
#include <iostream>
void Player::addProperty(Property p)
{
ownedProperties.push_back(p);
}
And finally main
#include "Player.h"
#include "Space.h"
#include "Property.h"
int main()
{
Player p{};
Property prop{};
prop.run(p);
system("pause");
}
Every time this is run I get a slew of errors, I'm sure it's got to do something with the circular include logic, with player including property, and property including space, which includes player. But, I don't see a workaround considering #include is needed to know how everything is defined isn't? Or are these errors referring to something else?
You have a circular include problem. Player includes Property which includes Space which includes Player again.
You can break the circle by not including Player.h in Space.h and only forward declare the class
#pragma once
class Player;
class Space
{
public:
virtual void run(Player&) = 0;
};
I'm pretty new to C++ and working with books and youtube and here in the same time, but i got a weird problem that I can't find a solution.
I'm trying to inherit from a base class "Mother" to a derived class Daughter and it is not working for me, it says it need to
This code was taking from TheNewBoston, so thank u Bucky, just giving credits
C:\CppProjects\inheritance\Daughter.h|6|error: expected class-name before '{' token
I'm adding the main and the classes:
main:
#include <iostream>
#include "Mother.h"
#include "Daughter.h"
using namespace std;
int main()
{
Daughter t;
t.sayName();
}
Mother class:
#include "Mother.h"
#include <iostream>
#include "Daughter.h"
using namespace std;
Mother::Mother()
{
}
void Mother::sayName(){
cout<<"I am !!!"<<endl;
}
Mother header:
#ifndef MOTHER_H
#define MOTHER_H
class Mother
{
public:
Mother();
void sayName();
};
#endif // MOTHER_H
Daughter class:
#include "Daughter.h"
#include <iostream>
#include "Mother.h"
using namespace std;
Daughter::Daughter()
{
}
Daughter header:
#ifndef DAUGHTER_H
#define DAUGHTER_H
class Daughter : public Mother
{
public:
Daughter();
};
#endif // DAUGHTER_H
I looked in most of the searches in here and nothing found, I even tried noob style and added std::, it has nothing to do with it.
thank you all of you who are willing to try!
just so you know, when I'm trying to put all of the code in one file, it works great:
the new main:
#include <iostream>
using namespace std;
class Mother
{
public:
Mother();
void sayName(){
cout<<"I am!!!!"<<endl;
}
};
class Daughter: public Mother
{
public:
Daughter();
};
int main()
{
Daughter t;
t.sayName();
}
The order of the declarations is important. At the moment in your Daughter class you include a header for Daughter and only afterwards Mother. This means that the compiler will see a definition "hi, I'm Daughter, I inherited Mother" and will stop there wondering "I've never met your Mother, I don't know what to do here."
The order of includes and definitions is important. Always have the base classes first.
Usually you either include the base header in the daughter header, or at least have a forward declaration to tell that the Mother class does exist. Also check up on header guards since you will need them.
I get the following error when I try to execute this code segment : "Menu does not name a type".I know its something to do with the circular references, but for the life of me I can't figure out what. Also, menu, go, and manager are repeatedly giving errors. The code segments are posted below :
#ifndef GO__H
#define GO__H
#include <SDL.h>
#include <iostream>
#include <string>
using std::cout; using std::endl;
using std::string;
#include "ioManager.h"
#include "gui.h"
#include "clock.h"
#include "menu.h"
//class Menu;
class Go {
public:
Go ();
void play();
private:
SDL_Surface *screen;
Gui gui;
Menu menu;
void drawBackground() const;
Go(const Go&);
Go& operator=(const Go&);
};
#endif
Here's Menu :
#ifndef MENU_H
#define MENU_H
#include <SDL.h>
#include <iostream>
#include "ioManager.h"
#include "gui.h"
#include "clock.h"
#include "manager.h"
class Menu {
public:
Menu ();
void play();
private:
const Clock& clock;
bool env;
SDL_Surface *screen;
Gui gui;
Manager mng;
void drawBackground() const;
Menu(const Menu&);
Menu& operator=(const Menu&);
};
#endif
Manager :
#ifndef MANAG_H
#define MANAG_H
#include "go.h"
class Manager {
Go go;
//other code
}
Can you see where the problem is? Error message:
In file included from go.h:13:0,
from manager.h:33,
from manager.cpp:2:
menu.h:28:11: error: field ‘mng’ has incomplete type
manager.h includes go.h which includes menu.h which includes manager.h ...
The class Menu is being defined before it ever gets to the definition of class Manager.
However, class Menu needs a Manager but since the compiler doesn't know about Manager yet it doesn't know how big to make it.
You could forward declare class Manager and make the mng member of Menu a pointer or reference:
class Manager;
class Menu {
...
Manager* mng;
// or this:
//Manager& mng;
...
Here's a good explanation of circular references and how to fix them.
It appears you are missing the semicolon at the end of the declaration of your Manager class in manger.h.
You are also missing the #endif to close your include guard.
So I am getting the following errors:
..\Actor.h:35: error: `Attack' is not a member of `RadiantFlux'
..\Actor.h:35: error: template argument 1 is invalid
..\Actor.h:35: error: template argument 2 is invalid
..\Actor.h:35: error: ISO C++ forbids declaration of `attacks' with no type
On this line (among others):
std::vector<RadiantFlux::Attack> attacks;
Here are the relevant files:
Actor.h:
#ifndef ACTOR_H_
#define ACTOR_H_
#include <string>
#include <vector>
#include "Attack.h"
namespace RadiantFlux {
...
class Actor {
private:
std::string name;
int health;
std::vector<RadiantFlux::Attack> attacks;
Attributes attributes;
public:
...
};
}
#endif /* ACTOR_H_ */
Attack.h:
#ifndef ATTACK_H_
#define ATTACK_H_
#include <string>
#include <stdlib.h>
#include <time.h>
#include "Actor.h"
namespace RadiantFlux {
...
class Attack {
private:
...
public:
...
};
}
#endif /* ATTACK_H_ */
Why am I getting these errors and what can I do to fix them? I am assuming it has something to do with the namespaces...
You have a cyclic dependency of your header files.
Attack.h includes Actor.h and vice versa.
Use Forward Declaration of class to avoid circular dependency problems.
Since the OP's comments, here is what needs to be done:
class Actor;
class Attack
{
};
If your code fails to compile after doing this, You need to read the linked answer and Understand why the error and how to solve it. The linked answer explains it all.
The classes Actor and Attack both refer to each other, so you will need to add a forward declaration in one of the file.
For example, in Actor.h:
class Attack;
class Actor
{
...
};