I have two classes both defined in separate header files. Each file has a field that is type of other class. Now I included in header of each file the header of other file, but compiler is generating errors. What am i missing?
You cannot have each class have "a field that is type of other class"; that would be a recursive definition and not only the compiler would not be able to make any sense out of it, it does not even make logical sense.
Each class having a field that is type of the other class is the kind of impossibility that you only see in M.C. Escher drawings, or animations thereof, like this one:
B. de Smit and H. W. Lenstra - Source: escherdroste.math.leidenuniv.nl
based on Escher's "Print Gallery" Lithograph, 1956, see Wikipedia
One of the two fields will have to be a pointer, so as to break the recursive containment, and avoid the logical impossibility.
Which brings us to the next problem: if class B is to contain an instance of class A, then obviously, A has to be declared before class B, so that A is already known to the compiler when compiling B. But if class A is declared before class B, how can we declare a pointer to B in A? Class B is not known yet at the time that A is compiled! The answer to this is a special construct known as forward declaration which exists precisely in order to accommodate situations like this. A forward declaration of class B looks like this:
class B;
All it is telling the compiler is that there will be a class called B. It does not tell the compiler anything about the contents of class B, so there is very little we can do with it, but we can do one thing: declare pointers to B.
So, the full solution to the problem looks like this:
file "A.h":
/* This is called a "forward declaration". We use it to tell the compiler that
the identifier "B" will from now on stand for a class, and this class will be
defined later. We will not be able to make any use of "B" before it has been
defined, but we will at least be able to declare pointers to it. */
class B;
class A
{
/* We cannot have a field of type "B" here, because it has not yet been
defined. However, with the forward declaration we have told the compiler
that "B" is a class, so we can at least have a field which is a pointer
to "B". */
B* pb;
}
file "B.h":
#include "A.h"
class B
{
/* the compiler now knows the size of "A", so we can have a field
of type "A". */
A a;
}
You shouldn't include the header files inside the other ones, just include the header files in your source files.
In the headers you can use a forward declaration:
// In Class1.h
class Class2;
// In class2.h
class Class1;
Also you can protect against a file being included twice using the preprocessor:
// Class1.h
#ifndef __CLASS_1_H
#define __CLASS_1_H
// content
#endif
I know this is an old topic but maybe you are still interested in solution!
Actually in C++ you can use two classes recursively without using pointers and here is how to do it.
file: a.h
#include <b.h>
class A {
B<> b;
}
file: b.h
class A;
template<typename T = A>
class B {
T a;
}
file: main.cpp
#include "a.h"
A a;
and that's all!
of course this is just for curiosity :)
You probably want to use forward declaration, unless you actually want to put instance of each class in each other. In which case you shouldn't use anything.
If B can only exist within A, I seem to be able to create A and B without using a pointer. B has to simply forward declare A and not include it (avoiding the recursive inclusion).
In my case, a Document has a Section which gets a reference to its Document.
section.h
class Document;
class Section
{
public:
Section(Document& document) : document{document} {}
private:
Document& document;
};
document.h
#include "section.h"
class Document
{
public:
Document() : section{*this} {}
private:
Section section;
};
main.cpp
#include "document.h"
int main()
{
Document document{};
}
This code compiles with g++ and runs on Linux.
A (complex) set of ifdef might enable it for other cases, but I'm not sure about the readability...
Besides the possibility of forward declaration - if it seems that you need two classes mutually within the other it is out of my experience a sign for a mistake in the depth of inheritance.
Eather the classes are a kind of siblings and you should create a parent class for both.
Or you are trying to use a class that is in fact a parent class within one that should have a sibling from this parent class. Then you should create this sibling as a third class.
Related
I got this syntax I don't really understand:
class USphereComponent* ProxSphere;
I think this means create a class, but is this class a pointer?
But the result is just creating an object called ProxSphere from an existing class USphereComponent.
What does this syntax actually mean, and what is its usage?
class Someotherclass; // That has not been defined yet
class HelloWorld
{
Someotherclass* my_pointer;
};
Or an alternative:
class HelloWorld
{
class Someotherclass* my_pointer;
};
The first one is obviously the correct one if you have multiple pointers (or references) to such class that has not been defined yet.
Is the second better? (I don't know) if you only need to do it once, otherwise doing
class HelloWorld
{
class Someotherclass* my_pointer;
class Someotherclass* my_pointer2;
class Someotherclass* my_pointer3;
void func(class Someotherclass* my_pointer, class Someotherclass& my_ref);
};
may not be the best.
Jts's answer is correct. I'd like to add a use case for it:
This is mostly used when you have a circular class dependency.
Like:
class A { B* binst; };
class B { A* ainst; };
That wouldn't compile since B isn't previously known.
Therefore you would first declare class B.
class B;
class A { B* binst; };
class B { A* ainst; };
Or as mentioned, you can use syntactic sugar:
class A { class B* binst; };
class B { A* ainst; };
Such a dependency might be a code smell. It also might be ok or even necessary. If you have it, you should carefully think if you can't do it in some other yet convenient way.
That particular syntax is called a "forward declaration". It is used to declare a type that has not been defined yet.
This is basically telling the compiler "There exists a class type named USphereComponent that you haven't seen yet that will come up later in the code. Please don't yell at me if you see pointers of that type". This allows you to declare pointer and reference for that forward-declared type.
Writing:
class USphereComponent* ProxSphere;
Is really just the equivalent of writing this:
class USphereComponent;
USphereComponent* ProxSphere;
The only difference with the second syntax, is that you only need to forward-declare the type once when you do it like this class USphereComponent;, otherwise you need to use the first syntax and add the class keyword before each usage of USphereComponent.
There are two main reasons why you may want to use a forward declaration:
This is probably the most common usage of forward-declaration in Unreal Engine. In header (.h) files, forward-declaration allows you to use pointer of classes for which you did not #include the corresponding header file. In our particular example that means that forward-declaring USphereComponent means that we don't need a #include "SphereComponent.h" statement (if we're just trying to pass a USphereComponent around that is).
Typically when that happens, the #include statement is simply done in the .cpp file. There are mainly two advantages of reducing the number of includes in your header files:
Compilation times are faster. Mind you, this mostly has significant impact on a codebase as big as Unreal's.
This reduces the number of public dependencies of you module (by making them "private" since your includes are now in your .cpp). This makes your module easier to be depended upon and also makes its interface cleaner.
Like other answers have said, forward-declaration can be used to break circular dependencies when you have two types that depends on each other in the same file:
class B;
class A
{
B* foo;
};
class B
{
A* bar;
};
I'm converting my old c++ program into OOP and as things grow bigger I'm splitting it per class in .h and .cpp files. The first class compiled nicely into an object file. But my second class is dependant on that first class and now I run into problems. Here my very simplified "all in a single file" code that works:
class A {
public:
void amethod(int) {
....code....
}
};
A a_obj; //object creation
class B {
public
void bmethod(void) {
a_obj.amethod(int);
}
};
B b_obj; //object creation
main() {
b_obj.bmethod();
}
After deviding the code over different files my .h files look like:
//file A.h:
class A {
public:
void amethod(int);
};
//file B.h
#include "A.h"
class B {
public
void bmethod(void);
};
In the implementation of class B there is the call to a_obj.amethod() and even I understand that g++ has no way to know that a_obj is an object of class A as I did not even include the a_obj object creating anywhere in the code.
How to solve this ? Is it something simple that I need to put the object creation somewhere in my .h or .cpp file (note that lots of other classes are using the same amethod()). I can not make everything static as I also have classes with multiple objects (in fact the same way of working is all over the program). Or is this way of working completely wrong (which would explain why I can not find any solution for this).
Is suggest you put more efforts in defining your interfaces.
If class B needs an instance of A to work, use parameters to pass an A:
class B {
public
void bmethod(A & a_obj) {
a_obj.amethod(int);
}
};
main() {
A a_obj;
B b_obj;
b_obj.bmethod(a_obj);
}
The problem is that your original code uses global data (i.e. the declarations of a_obj and b_obj are global). Globals are generally a bad idea because they can cause several problems. The 'proper' OOP way to do it would be to instantiate those objects in main(), and pass them to whatever other objects need to access them. You could pass references, pointers, or copies, depending on your needs.
With that said, if you really want to continue doing it with global data, then you can use an extern declaration. In each *.cpp file where you access a_obj, include this:
extern A a_obj;
That basically tells the compiler that there is an object with that name, but it exists somewhere else. I really don't recommend this approach if you're serious about learning OOP though.
I guess you are planning to use a_obj as global variable in other implementation file (.cpp).
So in header file B.h type extern reference to this instance.
extern A a_obj;
This declaration should help compile your B.cpp file. And ask actual instance a_obj during linking.
I didnt try this code, but telling by my experience and my practice(way) of coding. Hope this solution helps, else am sorry.
First, in order to call A::amethod() class B needs the full definition of class A and its amethod(). So you need to #include A.h before B.h in your .cpp files.
Next, if you address concrete a_obj object, you need to specify what that object is in order to link properly. In you first variant it was global object, so if it is what intended you can write: in A.cpp:
A a_obj;
in B.cpp:
extern a_obj;
// here you can call a_obj methods
But if these classes are so related that one calls methods of another, and also as I catched you need several objects of A and B, consider to connect these classes through inheritance:
class B : public A {
public:
void bMethod(int n) {
aMethod(n); // base class method call
}
// ...
or through delegation:
class B {
A m_A;
public:
void bMethod(int n) {
m_A.aMethod(n);
}
// ...
As mentioned earlier the way
void bMethod(A& a) {
a.aMethod();
}
will work, but the language has built-in means to express classes relationships.
How to implement is more design question, you can read more about this in Stroustrup 3rd edition, '24.3.5 Use Relationships'.
In C++ you can also pass a pointer to a member function of one class into the member function of another class to call a method from completely unrelated class (say, some callback), you can use boost::function and boost::bind for this. But it is advanced technique.
I'm not exactly certain what happens but take the following:
class A{
}
-
class B{
#include "A.h"
}
-
class C{
#include "B.h"
}
Now if I were to code in class C does it mean class A is also automatically included as well? From what I understand is that #include basically copies the entire file right on the spot.
Can anyone elaborate on this?
I'm trying to use class forwarding as much as I can. But sometimes I simply can not.
Edit:
The classes above are not in the same file. Imagine them separated.
Edit II:
Let me put it into more context.
Lets say I'm creating a new class that includes class B, but then I declare a variable of type A. This seems to compile even though I never included A to the class. Is this just how it goes in C++?
That would basically declare a nested class called A inside class B.
Cases where include directives should be anywhere else other than the top of the file are very rare, and usually have completely different purpose than what you have.
If I understood your file hierarchy correctly, it's equivalent to:
//A.h
class A{
};
//B.h
class B{
class A{
};
};
//C.h
class C{
class B{
class A{
};
};
};
You are right, the preprocessor just copies the headers in. Think of it like a long macro if you will.
A #include directive simply tells the compiler to pretend that the text in the named file had been written where the #include directive occurs. It has nothing to do with scopes, syntax, or anything else. It's simply text.
Without seeing the contents of A.h and B.h it's impossible to say anything more about what the effects of those #include directives are.
I just started programming in C++, and I've tried to create 2 classes where one will contain the other.
File A.h:
#ifndef _A_h
#define _A_h
class A{
public:
A(int id);
private:
int _id;
B _b; // HERE I GET A COMPILATION ERROR: B does not name a type
};
#endif
File A.cpp:
#include "A.h"
#include "B.h"
#include <cstdio>
A::A(int id): _id(id), _b(){
printf("hello\n the id is: %d\n", _id);
}
File B.h:
#ifndef _B_h
#define _B_h
class B{
public:
B();
};
#endif
File B.cpp:
#include "B.h"
#include <cstdio>
B::B(){
printf("this is hello from B\n");
}
I first compile the B class and then the A class, but then I get the error message:
A.h:9: error: ‘B’ does not name a type
How do I fix this problem?
The preprocessor inserts the contents of the files A.h and B.h exactly where the include statement occurs (this is really just copy/paste). When the compiler then parses A.cpp, it finds the declaration of class A before it knows about class B. This causes the error you see. There are two ways to solve this:
Include B.h in A.h. It is generally a good idea to include header files in the files where they are needed. If you rely on indirect inclusion though another header, or a special order of includes in the compilation unit (cpp-file), this will only confuse you and others as the project gets bigger.
If you use member variable of type B in class A, the compiler needs to know the exact and complete declaration of B, because it needs to create the memory-layout for A. If, on the other hand, you were using a pointer or reference to B, then a forward declaration would suffice, because the memory the compiler needs to reserve for a pointer or reference is independent of the class definition. This would look like this:
class B; // forward declaration
class A {
public:
A(int id);
private:
int _id;
B & _b;
};
This is very useful to avoid circular dependencies among headers.
I hope this helps.
error 'Class' does not name a type
Just in case someone does the same idiotic thing I did ...
I was creating a small test program from scratch and I typed Class instead of class (with a small C). I didn't take any notice of the quotes in the error message and spent a little too long not understanding my problem.
My search for a solution brought me here so I guess the same could happen to someone else.
NOTE: Because people searching with the same keyword will land on this page, I am adding this answer which is not the cause for this compiler error in the above mentioned case.
I was facing this error when I had an enum declared in some file which had one of the elements having the same symbol as my class name.
e.g. if I declare an enum = {A, B, C} in some file which is included in another file where I declare an object of class A.
This was throwing the same compiler error message mentioning that Class A does not name a type. There was no circular dependency in my case.
So, be careful while naming classes and declaring enums (which might be visible, imported and used externally in other files) in C++.
You must first include B.h from A.h. B b; makes no sense until you have included B.h.
The problem is that you need to include B.h in your A.h file. The problem is that in the definition of A, the compiler still doesn't know what B is. You should include all the definitions of all the types you are using.
Include "B.h" in "A.h". That brings in the declaration of 'B' for the compiler while compiling 'A'.
The first bullet holds in the case of OP.
$3.4.1/7 -
"A name used in the definition of a
class X outside of a member function
body or nested class definition27)
shall be declared in one of the
following ways:
— before its use in
class X or be a member of a base class
of X (10.2), or
— if X is a nested
class of class Y (9.7), before the
definition of X in Y, or shall be a
member of a base class of Y (this
lookup applies in turn to Y’s
enclosing classes, starting with the
innermost enclosing class),28) or
— if
X is a local class (9.8) or is a
nested class of a local class, before
the definition of class X in a block
enclosing the definition of class X,
or
— if X is a member of namespace N,
or is a nested class of a class that
is a member of N, or is a local class
or a nested class within a local class
of a function that is a member of N,
before the definition of class X in
namespace N or in one of N’s enclosing
namespaces."
when you define the class A, in A.h, you explicitely say that the class has a member B.
You MUST include "B.h" in "A.h"
Aren't you missing the #include "B.h" in A.h?
The solution to my problem today was slightly different that the other answers here.
In my case, the problem was caused by a missing close bracket (}) at the end of one of the header files in the include chain.
Essentially, what was happening was that A was including B. Because B was missing a } somewhere in the file, the definitions in B were not correctly found in A.
At first I thought I have circular dependency and added the forward declaration B. But then it started complaining about the fact that something in B was an incomplete type. That's how I thought of double checking the files for syntax errors.
Try to move all includes outside namespace.
//Error
namespace U2 {
#include <Head.h>
#include <LifeDiode.h>
}
//Solution
#include <Head.h>
#include <LifeDiode.h>
namespace U2 {
}
Not the answer, but for me the thing was that I forgot to add the std:: before the potential type to properly use it.
It actually happend to me because I mistakenly named the source file "something.c"
instead of "something.cpp".
I hope this helps someone who has the same error.
I have a program that uses enum types.
enum Type{a,b,};
class A
{
//use Type
};
class B
{
// also use that Type
};
2 class are located in 2 different files.
Should I put the type definition in a headfile or
in class definition for each class?
If the enum is going to be used in more than one .cpp file, you should put it in a header file that will be included by each. If there's a common header file, you should use that, otherwise you may as well create a new header file for this enum
You should always attempt to limit the scope of types in C++, so the enum should probably be declaread at class scope. The enum will typically belong slightly more naturally in one class than the other - lets say class A, so you put it in the declaration of A in the a.h header:
// a.h
class A {
public:
enum Type { a, b };
...
};
Now you need to include a.h in the header that declares B:
// b.h
#include "a.h"
class B {
public:
void f( A::Type t ); // use the Type enum
...
};
I can see the point of Neil: it is a pet peeve for many programmers to see stuff on the global scope. otoh, imho, introducing a class just for an enum is not a good style: It is supposed to be enum not a class. However, putting the same enum list in both classes (is what you were asking) would be the worst idea: we don't want to be repeating stuff.
Moreover, in most non-trivial codes, one might end up using more of such shared entities (more enums, const parameters, etc...) for implementation. So, I'd begin lumping all this into an implementation namespace (say "detail") which is a child namespace of your classes, and resides in a separate header file (say "detail.hpp"), included by all. For example:
// file A.hpp
#include "foo/detail.hpp"
namespace foo {
class A
{
// accessing enum as detail::a
};
}
// file B.hpp
#include "foo/detail.hpp"
namespace foo { class B { ... }; }
// file foo/detail.hpp
namespace foo { namespace detail {
enum { a,b, ... }
const int three = 3;
// etc...
// other implementation classes etc...
}}
And "detail" is nice and clean way of warning your class users to back off from whatever's declared in there. As your code gets bigger and these implementation details start growing in number you can break the dependencies into separate header files (detail1 detail2 etc...) and still keep one "detail" namespace (something which you can not do with a "class detail" for example).
The question is rather vague, but as a rule of thumb, you should try to minimize the redundancy in your code. Therefore, you should put the declaration of the enum to a header file.
It really depends on if the values are the same logical type, or if they just happen to have the same names. Would it make sense to assign an A::Type variable to a C::Type? If they are the same logical type, put them in a header that both include. To keep your build times low you probably want to put it in its own header file, but putting it in a shared header with other stuff works if you want to keep the number of files down.
Another option is to put the enum in a common base class that both inherit from (this may not make sense in this case, but it is another option).