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);
Related
I am new at C++ language and I am trying to understand why the next thing is happening:
I have a header file header.h
namespace myNamespace{
class myClass{
public:
myClass();
~myClass();
void myFunction(void);
}
void myVoid();
}
The definitions are in header.cpp
using namespace myNamespace;
void myClass::myFunction(void){
//DO anything
}
void myVoid(){
//Do anything
}
And in the main.cpp I have the follow:
#include "header.h"
main(){
myVoid();
myNamespace::myVoid();
}
Why If I try to call myFunction of the class myClass from the main I have a successful compile, and if I try to call the function as in the main file I have an undefined reference error? I can fix it if in the header.h moves myVoid out of the namespace.
Why is this happening? I am trying to figure out how this works.
Thanks in advice,
If you don't specify definition of myVoid (I mean just declaring it like you did), then the compiler can never be sure if you are implementing the function which is declared in namespace or just defining a new one.
On the other hand, if you are defining myClass::myFunction, it has to be the method that is declared in the defined class.
To make it clear, investigate the following code and take a look here (very similar question)
namespace Test {
int myVoid(void); // declaration
class yourClas; // declaration
class myClass{ // definition
public:
myClass();
~myClass();
void myFunction(void); // declaration which belongs to defined class
}
}
void myVoid() {
// definition, but compiler can't be sure this is the function
// that you mention in the namespace or a new function declaration.
}
void myClass::myFunction(void){
// absolutely definition for the method of the corresponding class
}
I have a problem in C++ that involves circular dependencies and inheritance.
I have implemented the design in parts and I will use pesudocode to ilustrate where the problem happens.
The first part is:
//app.h
include rel.h
class Rel; // forward declaration
class App {
shared_ptr<Rel> //member variable
}
//rel.h
include app.h
class App; //forward declaration
class Rel {
shared_ptr<App> //member variable
}
Until here, the program compiles without warnings
Then, I want to add inheritance as follows:
//app.h
include rel.h
include drel.h
class Rel; // forward declaration
class DRel // forward declaration
class App {
shared_ptr<Rel> //member variable
shared_ptr<DRel> //member variable
}
//rel.h (the same as before)
include app.h
class App; //forward declaration
class Rel {
shared_ptr<App> //member variable
}
//drel.h
include app.h
include rel.h
class App; //forward declaration
class DRel: Rel { // compile error here: expected class name before { token
shared_ptr<App> //member variable
}
As you see, the compiler throws "expected class name before { token" which means that Rel is not resolved, but why the first code without inheritance works and the second one doesn't? How can I fix that? Is that a "wrong" pattern?
I am using c++14
I know there are a lot of questions regarding the issues I am having, but I can't find the answer to my specific problem. Maybe I don't see it...
Since all the variables you declare do not need to know the space occupied by App, Rel and DRel, you don't even need to #include the headers in question, you just have to forward declare the name as you do.
So you have you .h with
class A;
class B;
class C {
std::shared_ptr<A> ptra;
std::shared_ptr<B> ptrb;
};
And then your .cpp with
#include "A"
#include "B"
C::C() { ... }
The original headers files needed to be guarded by #ifdefs like this:
#ifndef CYCLIC_DEPENDECY_1
#define CYCLIC_DEPENDECY_1
#include "cyclic_dependency2.h"
class Rel; // forward declaration
class App {
std::shared_ptr<Rel> test; //member variable
};
#endif
#ifndef CYCLIC_DEPENDECY_2
#define CYCLIC_DEPENDECY_2
#include "cyclic_dependency1.h"
class App; //forward declaration
class Rel {
std::shared_ptr<App> test;//member variable
};
#endif
#include <iostream>
#include <memory>
#include "cyclic_dependency2.h"
class Rel; // forward declaration
class DRel; // forward declaration
class DRel: Rel {
std::shared_ptr<App> test ;//member variable
};
main()
{
}
Note: I have found the issue with how my Xcode was compiling the below and it appears unrelated to the topic discussed herein. When I have more details I will provide them here.
I recommend voting to close my question as "too localized" since it was an Xcode problem, unrelated to the c++ code itself. Many thanks for the help all the same as I did learn from the answers.
The below question (now answered and resolved) was caused by a confusing exclusion of a file from the Xcode target, thus there were no compiler errors even though the file had problems.
I have a pure virtual interface and want to define its factory method, which returns a subclass of this interface. This works fine:
struct MyVirt{
...all virtual stuff
};
class SubVirt; //forward declaration allows factory:
MyVirt*CreateClass(){
return new SubVirt;
}
Update: Some of the comments say that forward declare is not enough to achieve the above, but that's not correct. You can accomplish the above fine without the full definition of the SubVirt class.
Now, what I want to do is have a custom constructor that takes arguments. As such:
MyVirt*CreateClass(){
return new SubVirt(arg 1, etc);
}
The problem is that a class forward declaration is no longer sufficient. It needs to see the class definition or its header. This means I can either move the factory method to the file where SubVirt is defined, or I have to include that file in the above file, which creates a circular dependency.
Is there a way to forward declare the custom constructor instead? That would make it all much simpler.
Your CreateClass function looks odd, you miss () in function definition. Should be like this:
MyVirt* CreateClass()
{
return new SubVirt(arg 1, etc);
}
When return a pointer, compiler needs to know the concrete type and constructor, so forward declare is not enough.
What you could do is:
in header file: forward declare SubVirt and CreateClass function
cpp file: include MyVirt.h and define CreateClass function
Separate declaration from implementation, like everyone does.
MyVirt.h:
struct MyVirt{
...all virtual stuff
};
MyVirt.cpp:
#include "MyVirt.h"
Implementation of MyVirt
SubVirt.h:
#include "MyVirt.h"
struct SubVirt : MyVirt {
...all SubVirt stuff
};
SubVirt.cpp:
#include "SubVirt.h"
Implementation of SubVirt
Factory.h:
struct MyVirt;
MyVirt *CreateClass();
Factory.cpp:
#include "SubVirt.h"
MyVirt *CreateClass() { return new SubVirt() }
This can be accomplished by separating the declaration and implementation.
The key here is to put the definition/implementation above the includes. Suppose you want to separate the classes A and B create two files like the following:
A.hpp
#ifndef A_HPP
#define A_HPP
struct B; // fwd. decl.
struct A {
int v;
A(int v) {
this->v = v;
}
B* createB();
};
#include "B.hpp"
A* B::createA() {
return new A(v);
}
#endif A_HPP
B.hpp
#ifndef B_HPP
#define B_HPP
struct A; // fwd. decl.
struct B {
int v;
B(int v) {
this->v = v;
}
A* createA();
};
#include "A.hpp"
B* A::createB() {
return new B(v);
}
#endif // B_HPP
main.hpp
#include <A.hpp>
#include <B.hpp>
#include <iostream>
int main(int argc, char *argv[]) {
A a(42);
std::cout << a.createB()->createA()->v << std::endl;
return 0;
}
You are of course free to move the implementation into a cpp file instead. This is only the basic recipe which shows how circular dependencies can be solved even for templated classes and functions.
http://codepad.org/IsBzQANX
If I'm creating a static library with a header file such as this:
// Myfile.h
#include "SomeHeaderFile.h" // External library
Class MyClass
{
// My code
};
Within my own project I can tell the compiler (in my case, Visual Studio) where to look for SomeHeaderFile.h. However, I don't want my users to be concerned with this - they should be able to include my header without having to inform their compiler about the location of SomeHeaderFile.h.
How is this type of situation normally handled?
This is a classic "compilation firewall" scenario. There are two simple solutions to do:
Forward-declare any classes or functions that you need from the external library. And then include the external library's header file only within your cpp file (when you actually need to use the classes or functions that you forward-declared in your header).
Use the PImpl idiom (or Cheshire Cat) where you forward-declare an "implementation" class that you declare and define only privately (in the cpp file). You use that private class to put all the external-library-dependent code to avoid having any traces of it in your public class (the one declared in your header file).
Here is an example using the first option:
#ifndef MY_LIB_MY_HEADER_H
#define MY_LIB_MY_HEADER_H
class some_external_class; // forward-declare external dependency.
class my_class {
public:
// ...
void someFunction(some_external_class& aRef); // declare members using the forward-declared incomplete type.
};
#endif
// in the cpp file:
#include "my_header.h"
#include "some_external_header.h"
void my_class::someFunction(some_external_class& aRef) {
// here, you can use all that you want from some_external_class.
};
Here is an example of option 2:
#ifndef MY_LIB_MY_HEADER_H
#define MY_LIB_MY_HEADER_H
class my_class_impl; // forward-declare private "implementation" class.
class my_class {
private:
std::unique_ptr<my_class_impl> pimpl; // a vanishing facade...
public:
// ...
};
#endif
// in the cpp file:
#include "my_header.h"
#include "some_external_header.h"
class my_class_impl {
private:
some_external_class obj;
// ...
public:
// some functions ...
};
my_class::my_class() : pimpl(new my_class_impl()) { };
Say the external header file contains the following:
external.h
class foo
{
public:
foo();
};
And in your library you use foo:
myheader.h:
#include "external.h"
class bar
{
...
private:
foo* _x;
};
To get your code to compile, all you have to do is to forward declare the foo class (after that you can remove the include):
class foo;
class bar
{
...
private:
foo* _x;
};
You would then have to include external.h in your source file.
In C++, I have a problem with circular dependencies / incomplete types. The situation is as follows:
Stuffcollection.h
#include "Spritesheet.h";
class Stuffcollection {
public:
void myfunc (Spritesheet *spritesheet);
void myfuncTwo ();
};
Stuffcollection.cpp
void Stuffcollection::myfunc(Spritesheet *spritesheet) {
unsigned int myvar = 5 * spritesheet->spritevar;
}
void myfunc2() {
//
}
Spritesheet.h
#include "Stuffcollection.h"
class Spritesheet {
public:
void init();
};
Spritesheet.cpp
void Spritesheet::init() {
Stuffcollection stuffme;
myvar = stuffme.myfuncTwo();
}
If I keep the includes as shown above, I get the compiler error
spritesheet has not been declared in Stuffcollection.h (line 4 in
the above). I understand this to be due to a circular dependency.
Now if I change #include "Spritesheet.h" to the Forward
Declaration class Spritesheet; in Stuffcollection.h, I get the
compiler error invalid use of incomplete type 'struct Spritesheet'
in Stuffcollection.cpp (line 2 in the above).
Similarly, if I change #include "Stuffcollection.h" to class
Stuffcollection; in Spritesheet.h, I get the compiler error aggregate
'Stuffcollection stuffme' has incomplete type and cannot be defined
in Spritesheet.cpp (line 2 in the above).
What can I do to solve this problem?
You should include Spritesheet.h in Stuffcollection.cpp
Just use forward declaration in the header file not the cpp file, that solves the circular dependency of the header file. The source file has no circular dependency actually.
Stuffcollection.cpp needs to know the complete layout of class Spritesheet(because you dereference it), So you need to include the header which defines the class Spritesheet in that file.
From your previous Q here, I believe that class Stuffcollection is used in the class declaration of Spritesheet header file and hence the above proposed solution.
Use this form for your nested includes:
Stuffcollection.h
#ifndef STUFFCOLLECTION_H_GUARD
#define STUFFCOLLECTION_H_GUARD
class Spritesheet;
class Stuffcollection {
public:
void myfunc (Spritesheet *spritesheet);
void myfuncTwo ();
};
#endif
Stuffcollection.cpp
#include "Stuffcollection.h"
#include "Spritesheet.h"
void Stuffcollection::myfunc(Spritesheet *spritesheet) {
unsigned int myvar = 5 * spritesheet->spritevar;
}
void Stuffcollection::myfuncTwo() {
//
}
Spritesheet.h
#ifndef SPRITESHEET_H_GUARD
#define SPRITESHEET_H_GUARD
class Spritesheet {
public:
void init();
};
#endif
Spritesheet.cpp
#include "Stuffcollection.h"
#include "Spritesheet.h"
void Spritesheet::init() {
Stuffcollection stuffme;
myvar = stuffme.myfuncTwo();
}
General rules I follow:
Don't include an include from an include, dude. Prefer forward declarations if possible.
Exception: include system includes anywhere you want
Have CPP include everything it needs, not relying upon H recursively including it files.
Always use include guards.
Never use pragma
Spritesheet.h doesn't need to include Stuffcollection.h, since no Stuffcollection is used in the class declaration of Spritesheet. Move that include line to Spritesheet.cpp instead and you should be fine.