So, i started learning C++ about a year ago, i learned Java C# and VB.NET before it.
As it is now, i would consider myself a advanced C++ coder. However, theres one thing i dont quite get. The linking process. And heres the problem.
Right now, im coding a XNA-like library for Game development, with a basic Component System -
but i get Compiler errors when building it, C++ pretending it doesnt know a specific type, in this case, the GameComponent class doesnt know the ComponentSelector class (and vice versa), although its correctly included and typed. Im gonna show you my two header files, hopefully you can help me out.
ComponentSelector.hpp:
#ifndef COMPONENTSELECTOR_HPP
#define COMPONENTSELECTOR_HPP
#include<sem/System/Types.hpp>
#include<sem/System/GameComponent.hpp>
#include<vector>
namespace sem
{
class ComponentSelector
{
public:
GameComponent* getComponent1(); //GameComponent does not name a type
GameComponent* getComponent2(); //GameComponent does not name a type
GameComponent* getComponent3(); //GameComponent does not name a type
void addComponent(GameComponent* item); //GameComponent does not name a type
void removeComponent1();
void removeComponent2();
void removeComponent3();
void clearList();
private:
std::vector<GameComponent*> m_Components;
protected:
};
}
#endif // COMPONENTSELECTOR_HPP
GameComponent.hpp:
#ifndef GAMECOMPONENT_HPP
#define GAMECOMPONENT_HPP
#include<sem/System/ComponentSelector.hpp>
#include <sem/System/Types.hpp>
namespace sem
{
class GameComponent
{
public:
virtual void load() = 0;
virtual void unload() = 0;
virtual void update() = 0;
virtual void draw() = 0;
ComponentSelector* m_Selector; //ComponentSelector does not name a type
SEMlong getID();
SEMstring getName();
SEMstring getType();
private:
SEMlong m_ComponentID;
SEMstring m_ComponentName;
SEMstring m_ComponentType;
protected:
};
}
#endif // GAMECOMPONENT_HPP
Any solution and tips would be greatly appreciated.
You need a forward declaration for class ComponentSelector in your GameComponent class declaration:
// Remove this: #include<sem/System/ComponentSelector.hpp>
#include <sem/System/Types.hpp>
namespace sem
{
class ComponentSelector; // Note the forward declaration added!
class GameComponent
{
// ...
ComponentSelector* m_Selector; // Compiles now!
// ...
I'd recommend to do the same in the ComponentSelector declaration header vice versa. Include the full class declarations then, where you are going to use any members (this is in the compilation units i.e. .cpp-files usually).
Related
I'm trying to create an abstract class, which is used as a "template" for deriving classes.
I created a vector (stack) in which I store pointers to said abstract class, since you can't call member functions from an abstract class itself (thankfully ;))
But when I compile my classes, I get the following error:
error: invalid use of incomplete type 'class GameState'
this->_states.top()->Cleanup();
^~
I already tried many things and I think the problem is, that I have a forward declaration of the GameState class inside the Game class, because they both have to know of each other. Could that be the problem?
For viewing purposes, here are the snippets of my code:
GameState.hpp:
#include "Game.hpp"
class GameState {
public:
Game *game;
virtual void Init()=0;
virtual void Cleanup()=0;
... (etc.)
protected:
GameState(){}
};
Game.hpp:
#include <stack>
#include <SFML/Graphics.hpp>
#include "TextureManager.hpp"
// I GUESS THAT THIS DECLARATION IS THE PROBLEM!
class GameState;
class Game {
public:
TextureManager *TextureMgr;
sf::RenderWindow Win;
Game();
~Game();
... (etc.)
bool IsRunning() { return this->running; }
bool Quit() { this->running = false; }
private:
std::stack<GameState*> _states;
bool running;
};
Game.cpp:(calling example of member function)
void Game::Cleanup() {
while (!this->_states.empty()) {
this->_states.top()->Cleanup();
this->_states.pop();
}
}
Thank you very much in advance. And if the forward declaration is the problem; do you probably know any article or book, where such problems, where two classes have to know of each other, are described with different approaches for a solution?
I've already searched in a bunch of books, but I can't really find one, which got my eye.
You need to include GameState.hpp into Game.cpp so GameState will be complete at that point. Forward declaration allows to declare std::stack<GameState*> however a definition should be available to call class methods.
I have been developing a C++ game engine for a long time. I have never had any issues with the compiler, or anything like that, until I update to Xcode 8.3.1!
Suddenly, it appears that a default setting was changed when I updated that made it so that the compiler simply cannot handle circular references.
Does anyone know how to set this back, (I tried downgrading Xcode, and it still doesn't work!)
My circular referencing looks something like this:
I have a class called "Object" defined in my code
"Object" includes another class called "Renderer2D"
"Renderer2D" includes another class called "Renderable2D"
"Renderable2D" extends "Object"
My "Object" class:
#pragma once
#include "Graphics/2D/Renderer2D.h"
namespace kineticengine {
class Object {
public:
Object();
virtual ~Object() {}
virtual void render(graphics::Renderer2D* renderer) const;
};
}
My "Renderer2D" class:
#pragma once
#include "Renderable2D.h"
namespace kineticengine {
namespace graphics {
class Renderer2D {
protected:
Renderer2D() {}
public:
virtual void submit(const Renderable2D* renderable) {}; // Error here, "Unknown type name 'Renderable2D', did you mean 'Renderer2D'?"
};
}
}
My "Renderable2D" class:
#pragma once
#include "Renderer2D.h"
#include "../../Object.h"
namespace kineticengine {
namespace graphics {
class Renderable2D : public Object {
public:
Renderable2D() : Object() {}
virtual ~Renderable2D() {}
void render(Renderer2D* renderer) const override {
renderer->submit(this); // Error here "Cannot initialize parameter of type 'const kineticengine::graphics::Renderer2D *' with an rvalue of type 'const kineticengine::graphics::Renderable2D *'"
}
};
}
}
All of my errors are basically variations of "Unknown class [x]" where x is one of the other classes.
Any help would be appreciated!
Renderable2D.h is including Renderer2D.h before defining class Renderable2D, so when Renderer2D.h refers to class Renderable2D, it is not yet defined. Clang is behaving correctly.
One way to break this cycle is to not include headers if you're only going to refer to a class by pointer or reference. You then put a forward declaration for the class in instead of the include directive. This has the added bonus of speeding up compile time as well.
I am currently very new to c++, i have started learning how to use pointers in a path finding algorithm.
I am having an issue with calling a function within a class that is derived from a base class.
The specific piece of code causing issue is:
FreeTile *tempPointer = new FreeTile();
cout<<tempPointer->getFree()<<endl;
mapp[i][j] = tempPointer;
when i call getFree (which returns a boolean value) i get the error:
undefined reference to Tile::getFree(). Tile being the base class.
The header for FreeTile is:
#ifndef FREETILE_H
#define FREETILE_H
#include "Tile.h"
class FreeTile:public Tile
{
public:
FreeTile();
virtual ~FreeTile();
void setParent(FreeTile* par);
int getF();
int getG();
int getH();
void setF(int in);
void setG(int in);
void setH(int in);
FreeTile* getParent();
protected:
private:
int F;
int G;
int H;
bool free;
};
Tile header is:
#ifndef TILE_H
#define TILE_H
class Tile
{
public:
Tile();
virtual ~Tile();
bool getFree();
void setFree(bool bo);
protected:
private:
bool free;
};
#endif // TILE_H
#endif // FREETILE_H
Finally the cpp file for Tile:
#include "Tile.h"
#include <iostream>
using namespace std;
bool free;
Tile::Tile()
{
cout<<"Constructor Called"<<endl;
}
Tile::~Tile()
{
//dtor
}
bool getFree(){
return free;
}
void setFree(bool bo){
free = bo;
}
If you need more code or if im missing something blatant feel free to shame me as much as you like :P
Thanks in advance.
On a side note, can you initiate a private variable in a constructor such as free = true as when doing this it states the variable is private.
In the Cpp file rename "bool getFree()" to
"bool Tile::getFree()"
In your implementation the function is just a regular c gloabl function.
In the fixed version it is the class function implementaion of the function you declare in the header file
Also
1st in your Tile you have a private variable "bool free"
in the cpp file you have a global variable "bool free"
this is confusing.
Probably want to delete the one you declared in the cpp file.
Want a deeper explanation?
Yeah! my 1st answer!
Deeper Explanation:
the function you declared in the Class Tile is not defined (just declared) because you didn't add "Tile::" before the function definition in the cpp file (i.e you didn't define a scope).
The function you wrote in the cpp file is both defined and declared in the cpp file, so only functions written after it in the cpp file can call it (works same a c).
Probably when you wrote the function it didn't know that "free" was, right? because it was not a class function. so you added the global "bool free" but that is a completely different variable.
Glad to help!
don't forget to mark this as answered!
I'm trying to build a solution which has three files. With main.cpp it is four files.
Entity.h
#pragma once
#include "SystemBase.h"
namespace Engine {
class Entity {
public:
Entity() { }
void s(SystemBase* sb) { }
};
}
SubscribersList.h
#pragma once
#include "SystemBase.h"
#include "Entity.h"
namespace Engine {
class SubscribersList {
friend SystemBase;
public:
SubscribersList() { }
void f(Entity* e) { }
};
}
SystemBase.h
#pragma once
#include "SubscribersList.h"
#include "Entity.h"
namespace Engine {
class SystemBase {
public:
SystemBase() { }
void g(Entity* e) { }
private:
SubscribersList m;
};
}
Don't focus on the body's of methods in the headers. It is just to keep things simple. I found two ways to build the solution.
1. Write the word class before all class names. But it crashes when I try to separate the realization from prototypes.
2. Write all code in one file.
I don't/won't write the keyword class before all class names to build the solution, and certainly I don't/won't write a big project in one file. So why I can't build it? What is the magic?!
To understand the problem of cyclic header dependency we first need understand the difference between a class declaration and definition and the concept of incomplete types.
A prototype or forward declaration of a type Type is written as:
class Type;
Such a forward declaration allows you to create pointers and reference to that type.
You cannot however instantiate, dereference pointers to or use a reference to Type until its full type is declared.
A declaration for Type could be written as:
class AnotherType;
class Type {
public:
void aMemberFunc();
private:
AnotherType *m_theOtherThing;
};
Now we have the declaration instances can be created and pointers to Type can be dereferenced.
However before m_theOtherThing is dereferenced or instanciated AnotherType must be fully declared.
class AnotherType {
Type m_aType;
}
Should do, which gives us both the full declaration and definition of AnotherType.
That allows to continue on to write the definition of Type::aMemberFunc:
void Type::aMemberFunc() {
m_theOtherThing = new AnotherType();
}
If instead of presenting this code to the compiler in this order we instead presented the full declarations of Type and AnotherType up front:
class Type {
public:
void aMemberFunc();
private:
AnotherType *m_theOtherThing;
};
class AnotherType {
Type m_aType;
}
Then AnotherType *m_theOtherThing; will fail to compile as AnotherType has not been declared or forward declared by that point.
Switching the order gives:
class AnotherType {
Type m_aType;
}
class Type {
public:
void aMemberFunc();
private:
AnotherType *m_theOtherThing;
};
Now Type m_aType; will not compile as Type has not been declared. A forward declaration would not do in this case.
Using #pragma once instead of header guards does not in anyway change the problem. #pragma once only ensures the header is include just once it does not effect the order the compiler processes the code otherwise. It certainly does not allow the compiler to ignore undefined types when it reaches them.
For this kind of class structure there is no way for the compiler to be able to process it without the use for forward declarations.
Im having a little problem with classes.
Here is some of my code:
//GameMap.h
#ifndef GAMEMAP_H
#define GAMEMAP_H
#include "apath.h"
class GameMap
{
/*class definition here*/
};
#endif
and
//apath.h
#ifndef APATH_H
#define APATH_H
class path
{
//some code...
void DoSomething(GameMap map);
//rest of class body
};
#endif
I cant use GameMap in apath.h, when I try to include "GameMap.h in this file I get some stupid errors... I also tried to add class GameMap; before definition of path class. Nothing helped... I really need to use it here...
If needed I can post some more code.
Thanx for any replies!
You should use forward declaration of class GameMap in apath.h:
class GameMap; // forward declaration
class path
{
//some code...
void DoSomething(GameMap map);
//rest of class body
};
Check: When can I use a forward declaration?
In following example I use forward declaration of class A so that I'm able to declare function useA that uses it:
// file a.h
class A;
void useA(A a);
and then in main.cpp I have:
#include "a.h"
class A
{
public:
void foo() { cout << "A"; }
};
void useA(A a)
{
a.foo();
}
which is absolutely correct, since class A is already defined here.
Hope this helps.
You should check PIMPL idiom.
In path header:
class GameMap;
class Path
{
public:
void useMap( GameMap * map );
};
In path source:
#include "Path.h"
#include "GameMap.h"
void Path::useMap( GameMap * map )
{
// Use map class
}
More links: link and connected topic.
You have a circular include problem. GamePath.h includes apath.h, so trying to include GamePath.h in apath.h is brittle at best and gives errors (your case) at worst. The best bet is to find which pieces of apath.h are used by GamePath.h, and refactor those into a common header file, say common.h, and include common.h in both GamePath.h and apath.h. That way you don't have a circular include anymore, and you can draw a graph of includes as a nice beautiful DAG.
You're trying to do circular includes, which are obviously forbidden.
I'd suggest you forward declare GameMap in apath.h and pass it as a const reference:
class GameMap; // forward declaration
class path
{
//some code...
void DoSomething(const GameMap &map);
//rest of class body
};
const ref is better than simple ref since it tells explicitly that the object cannot change during the function call.
make external declaration in apath.h
class GameMap;
After it change signature of method:
void DoSomething(GameMap& map);
Or
void DoSomething(GameMap* map);