I have class1 that needs header of class2.And class2 that needs header of class1 to be included.
I included header of class2 in class1 and header of class1 in class2 and troubles began (in class2 I get error that says that class1 instance do not name a class)
Please can someone explain how to deal with this situation because I googled this question but didn't get what to do
thank you
One often applicable solution to this is to simply forward-declare the classes. For example:
class1.h
#ifndef CLASS1_H
#define CLASS1_H
class Class2;
class Class1 {
public:
// ...
private:
// ...
std::unique_ptr<Class2> owned_child_;
// ...
};
#endif
class2.h
#ifndef CLASS2_H
#define CLASS2_H
class Class1;
class Class2 {
public:
// ...
private:
// ...
const Class1* unowned_parent_;
// ...
};
#endif
Note, however, that this strategy only works so long as you do not write code that requires the definition of the class to be available, which can be achieved when using pointers or references to the class's type. As soon as you use the class type without a reference or pointer, you will need to have available the full declaration of the class already processed and available.
Related
I am trying to use a struct of one class in another class. My first class looks like this:
Class1.h
#ifndef CLASS1_H
#define CLASS1_H
class Class1
{
public:
Class1();
~Class1();
struct St{
int x;
}
St struct1;
private:
};
#endif
Now in the header of the second class, I want to use this struct and variable.
Class2.h
#ifndef CLASS2_H
#define CLASS2_H
#include "Class1.h"
class Class2
{
public:
Class2();
~Class2();
St struct2;
private:
};
However, it says:
identifier "St" is undefined.
When I use it this way:
Class1::St struct1;
the error goes away. What are the issues with my code?
What are the issues with my code?
The issue is St is a nested class. Its fully qualified name is ::Class1::St1. Within the scope of Class2, the unqualified name lookup does not use the scope of Class1, so no declaration of St will be found.
You can fix the issue by doing the following:
When I use it this way:
Class1::St struct1;
the error goes away.
Well I have 2 classes in 2 header and 2 cpp files
#class1.h
#ifndef class1_h
#define class1_h
class myclass;
#endif
#class2.h
#ifndef class2_h
#define class2_h
class anotherclass;
#endif
#class1.cpp
class myclass
{
anotherclass test1;
}
#class2.cpp
class anotherclass
{
myclass test2;
}
And of course a simple main
Well I think it's obvious why this thing wont even compile
my question here is how to make it compile?
Having the classes in different files is mandatory..
If the class definitions (the bodies that is) must be in separate files then the members of the declared type can only be a pointer (or a reference but that is unusual). You would then need a function in the source file where the class is actually defined that returns a pointer-to-instance of the type.
MyClass.h:
#if !defined(MYCLASS_H)
#define MYCLASS_H
class MyClass;
MyClass * CreateMyClass();
#endif
OtherClass.h:
#if !defined(OTHERCLASS_H)
#define OTHERCLASS_H
class OtherClass;
OtherClass * CreateOther();
#endif
myclass.cpp
#include "otherclass.h"
class MyClass
{
OtherClass * ptrOther;
public:
MyClass()
: ptrOther(CreateOther())
{}
};
otherclass.cpp:
#include "myclass.h"
class OtherClass
{
MyClass * ptrMyClass;
public:
OtherClass()
: ptrMyClass(CreateMyClass())
{}
};
Note that doing things this way you would not actually be able to do anything with ptrOther or ptrMyClass ((possibly not even free them correctly), It would be much more typical to place the class definitions in the header and separate out the member definitions (for functions and statics), like the following:
MyClass2.h:
#if !defined(MYCLASS2_H)
#define MYCLASS2_H
#include "OtherClass.h"
class MyClass2
{
OtherClass * ptrOther;
public:
MyClass2();
};
#endif
cMyClass.cpp:
#include "MyClass2.h"
MyClass2::MyClass2()
: ptrOther(CreateOther())
{}
Header files define class interfaces. Source code '.cpp' files are using for the implementation. Your source code has the implementation and the class interface.
I've got a class:
class SOMECLASS
{
public:
(...)
static SOMESTRUCT GetInfo();
};
And a struct:
struct SOMESTRUCT
{
(...)
SOMECLASS Instance;
};
They are declared in SOMESTRUCT.h and SOMECLASS.h
I'm not able to compile it, even with forward declarations.
I'm still getting:
error: field ‘Instance’ has incomplete type
How can I solve that?
Try the following
SOMECLASS.h
#ifndef SOMECLASS_H
#DEFINE SOMECLASS_H
class SOMECLASS
{
public:
(...)
static struct SOMESTRUCT GetInfo();
};
#endif // SOMECLASS_H
SOMESTRUCT,h
#ifndef SOMESTRUCT_H
#DEFINE SOMESTRUCT_H
#include "SOMECLASS.h"
struct SOMESTRUCT
{
(...)
SOMECLASS Instance;
};
#endif // SOMESTRUCT_H
The answers given above would have been correct if the users include SOMESTRUCT.h.
If the user do this
#include "SOMECLASS.h"
int main()
{
SOMECLASS::GetInfo();
}
The same error would occur.
The reason is the compiler has to know the full definition of the return variable; otherwise it cannot know how to construct it when the function returns.
When SOMECLASS.h is included, the compiler only knows the identifier SOMESTRUCT is a sturct. If the user calls SOMECLASS::GetInfo, the function has to construct a SOMESTRUCT, so the full definition of the struct has to be given before that line in the same file.
To solve it, it is more reasonable to include SOMESTRUCT.h in SOMECLASS.h, so the user can be sure that calling any function in the class would not result in compilation error, as long as they include the header.
One should also forward declare class SOMECLASS in SOMESTRUCT.h.
If there are cases that only SOMESTRUCT.h is used, then the SOMECLASS.h should also be included in SOMESTRUCT.h, because constructing SOMESTRUCT requires the definition of SOMECLASS.h.
You could avoid this is by declaring Instance variable as SOMECLASS& or SOMECLASS* instead of SOMECLASS.
If you really don't want to expose the detailed definition of the SOMESTRUCT, you can try these
define an IInfo interface class with virtual accessor to get information from SOMESTRUCT
use pimpl idiom
By these ways you don't have to include SOMESTRUCT.h in SOMECLASS.h.
this maybe a little trivial but I'm puzzled with such problem.
I want to create two classes Class1, Class2. Both classes should contain a field that contains pointer to instance of the other class. So they should be cross linked.
If I do it like this then I get an error from the compiller saying:
- ISO C++ forbids declaration of 'Class1' with no type
- expected ';' before * token
Please help :)
file: class1.h
#ifndef CLASS1_H
#define CLASS1_H
#include "class2.h"
class Class1 {
public:
Class1();
private:
Class2* link;
}
#endif
file: class2.h
#ifndef CLASS2_H
#define CLASS2_H
#include "class1.h"
class Class2 {
public:
Class2();
private:
Class1* link;
}
#endif
Add class declaration (as opposed to definition) before you use it. For example, you could have:
#ifndef CLASS1_H
#define CLASS1_H
class Class2;
class Class1
{
public:
Class1();
private:
Class2* link;
}
#endif
and do the same for Class2.h.
The problem is the circular dependency; each header is trying to include the other, which is impossible.
You don't need the full definition of each class in order to declare a pointer to it; you can replace each #include line with a forward declaration (class Class1; and class Class2;), and then everything should compile happily.
I have two classes and both of them uses some of the other class, on example:
// class1.h
class Class1;
#include "class2.h"
class Class1 {
public:
static Class2 *C2;
...
};
// class2.h
class Class2;
#include "class1.h"
class Class2 {
public:
static Class1 *C1;
...
};
And when I define it like in example above, it works (I also have some #ifndef to avoid infinite header recurency). But I also want to add some inline functions to my classes. And I read here that I should put definition of inline function in header file, because it won't work if I'll put them in cpp file and want to call them from other cpp file (when I do it I get undefined reference during linking). But the problem here is with something like this:
// class1.h
...
inline void Class1::Foo() {
C2->Bar();
}
I get error: invalid use of incomplete type ‘struct Class2’.
So how can I do it?
You need to delay including the header, but then include it and define your inline methods. By doing this in each header, they are self-sufficient and including one will always include the other, with include guards preventing infinite recursion.
A.hpp
#ifndef INCLUDE_GUARD_B9392DB18D114C1B8DFFF9B6052DBDBD
#define INCLUDE_GUARD_B9392DB18D114C1B8DFFF9B6052DBDBD
struct B;
struct A {
B* p;
void foo();
};
#include "B.hpp"
inline
void A::foo() {
if (p) p->bar();
}
#endif
B.hpp
#ifndef INCLUDE_GUARD_C81A5FEA876A4C6B953D1EB7A88A27C8
#define INCLUDE_GUARD_C81A5FEA876A4C6B953D1EB7A88A27C8
struct A;
struct B {
A* p;
void bar();
};
#include "A.hpp"
inline
void B::bar() {
if (p) p->foo();
}
#endif
You have it mix'd up. What you want is:
// class1.h
class Class2;
class Class1 {
public:
static Class2 *C2;
...
};
// class2.h
class Class1;
class Class2 {
public:
static Class1 *C1;
...
};
And include the respective headers in the source. The line:
class Class1; // or Class2
Declares an incomplete type, and you can have pointers and references to incomplete types. Upon usage, though, it needs to be complete. So just say "hey it'll exist!" in the header, and in the source tell it what it is.
My suggestion is that you place common methods and members into a base class, then derive C1 and C2 from the base class. This may fix the circular dependency issue.