I have two classes which both need to have links to objects of one another. Here's some example code to show my issue:
//object1.h
class object1{
object2 *pointer;
}
My other class:
//object2.h
class object2{
object1 *pointer;
}
I'm not exactly sure how I'm supposed include the two classes simultaneously in each other's file. Having an include for the other class in both files is causing me issues. Preferably, I would like to just have both the objects in one file, since their headers are only a few lines of code each, but this causes an error on whichever class is first declared in the file, since the other class header isn't preceeding it; It gives me an invalid type error.
Use a forward declaration:
//object1.h
class object2;
class object1{
object2 *pointer;
};
//object2.h
class object1;
class object2{
object1 *pointer;
};
A forward declaration introduces an incomplete type.
In short, it tells the compiler that the definition exists somewhere else.
You have some limitations with incomplete types, though. Since the compiler doesn't know its full definition, it cannot do things like allocating enough space for it, invoking member functions, checking the virtual table, etc.
Fundamentally, what you can do is to just declare references/pointers to them and pass'em around:
// Forward declaration
class X;
class Y {
private:
// X x; // Error: compiler can't figure out its size
X &x; // A reference is ok
public:
Y(X &x) : x(x) { }
// void foo() { x.foo(); } // Error: compiler can't invoke X's member
void bar();
};
// Full declaration
class X {
public:
void foo() { }
};
void Y::bar()
{
x.foo(); // Now it is OK to invoke X's member
}
A good pattern is to use forward declarations to break dependency cycles between headers or class definitions and make you wonder whatever your design could be improved.
Related
Is some one able to explain why header files have something like this?
class foo; // This here?
class bar
{
bar();
};
Do you need an include statement when using this?
Thanks.
The first class foo; is called a forward declaration of the class foo. It simply lets the compiler know that it exists and that it names a class. This makes foo what is called an "incomplete type" (unless the full declaration of foo has already been seen). With an incomplete type, you can declare pointers of that type, but you cannot allocate instances of that type or do anything that requires knowing its size or members.
Such forward declarations are frequently used when two types each may have pointers to each other, in which case both need to be able to express the notion of a pointer to the other type, and so you would have a circular dependency without such a thing. This is needed mostly because C++ uses a single pass mechanism for resolving types; in Java, you can have circular dependencies without forward declarations, because Java uses multiple passes. You may also see forward declarations where the author is under the misguided impression that using forward declarations instead of including the required header reduces compile time; that, of course, is not the case, because you need to include the full declaration (i.e. the header), anyway, and if preprocessor guards are used, then there is basically no difference in compile time.
To answer your question on whether you need the include or not... assuming you only need a partial type, then your header does not need to directly include the header for the type that has been forward declared; however, whoever makes use of your header, when they use your type will need to include the header for the forward declared type, and so you might as well just include the other header.
That's a forward declaration. You need it for example if class bar has a pointer to a foo object, but you don't want to include the whole definition of the foo object immediately.
this is a forward declaration of the class.
In my experience, this is typically done when you have a circular dependency.. for example
in foo.h
--------
#include "bar.h"
class foo
{
public:
foo(bar *bar);
private:
foo *m_foo;
};
and in bar.h
------------
class foo;
class bar
{
public:
void methodFooWillCall();
protected:
std::list<foo *> myFoos;
}
Just curious, why do we need the term forward declaration at all? Isn't a forward declaration simply a declaration (as opposed to a definition)?
class X; // declaration
class X // definition
{
int member;
void function();
};
That's a forward declaration. Consider the following example:
class foo; // you likely need this for the code beneath to compile
class bar {
void smth( foo& );
};
If you haven't included the definition of class foo in such a way that the compiler sees it before compiling the definition of class bar the code will not compile (the compiler will say it doesn't know what foo means) unless you have the forward declaration.
It's a forwards declaration of the class 'foo'. It allows you to declare pointers and references to the class, but not use it (eg. call members or determine its size), because it's not yet defined! It must later be followed up with a full, normal declaration (class foo { ... };).
It's useful for things like declaring two classes which hold pointers to each other, which otherwise would be impossible to set up.
This is called forward declaration. The body of the class foo would be defined at a later part of the file. Forward declaration is done to get around cyclic dependencies: The definition of class Bar requires class Foo and vice versa.
class Bar
{
Foo * foo;
};
class Foo
{
Bar * bar;
};
As you can see, Bar has a reference to Foo and vice versa. If you try to compile this, the compiler will complaint saying that it doesn't know anything about Foo. The solution is to forward declare the class Foo above the Bar (just like you declare the prototype of a function above the main and define its body later).
class Foo; //Tells the compiler that there is a class Foo coming down the line.
class Bar
{
Foo * foo;
};
class Foo
{
Bar * bar;
};
This is called a forward declaration. It is used to make your code aware that the class foo exists. This in turn can be used by the class bar.
It's commonly used to solve circular includes problems. Take this for example
//a.h
#include "b.h"
class A
{
void useB(B obj);
}
and
// b.h
#include "a.h"
class B
{
void useA(A obj);
}
This causes a circular include problem, because a.h includes b.h which in turns includes a.h, to infinity. You can solve this problem by making a forward declaration of each class in each header, like so :
//a.h
class B;
class A
{
void useB(B obj);
}
// b.h
class A;
class B
{
void useA(A obj);
}
Note : Very often when you have a circular include problem, this is indicative of a conception/modelling problem. You should probably ask yourself if your classes are well defined before trying to solve your problem with forward declarations.
Try to think of writing this:
file bar.h:
#include "bar.h"
class Foo
{
Bar* bar_ptr;
}
file foo.h:
#include "foo.h"
class Bar
{
Foo* foo_ptr;
}
This won't work, first due to infinite #include chain, then if you get rid of one of the includes, either Foo won't know what Bar is, or Bar won't know what Foo is.
Try this instead:
class Bar;
class Foo
{
Bar* bar_ptr;
};
file foo.h:
class Foo;
class Bar
{
Foo* foo_ptr;
};
Let's say I have 2 classes, player and npc. In the header file for class player, could I have a function that has an npc class object as a parameter?
For instance:
player.h:
void somefunc(npc npc1);
Yes, this is allowed, as long as a definition or forward declaration for the type has been encountered yet. You can also have pointers or references to other types, and even parameters of the same class' type.
class A {};
class B {
public:
void funcA(A a) {}
void funcAPtr(A* p) {}
void funcARef(A& r) {}
void funcB(B b) {}
};
// ...
A a;
B b;
b.funcA(a);
This is actually one of the key tenets of object-oriented programming.
In your case specifically, you would want to have a definition for npc first, so it might look something like this:
// npc.h
class npc {};
// -----
// player.h
#include "npc.h"
class player {
public:
void somefunc(npc npc1);
};
Or, if you have function bodies in a .cpp file, you can just put a forward declaration in the header, and include npc.h in the source file. This is usually safer, especially in cases where you may encounter circular dependency issues.
// npc.h
class npc {};
// -----
// player.h
class npc;
class player {
public:
void somefunc(npc npc1);
};
// -----
// player.cpp
#include "player.h"
#include "npc.h"
void player::somefunc(npc npc1) {}
// Note that "npc"'s header must be included before the type is actually used.
// For example, it needs to be included before the function's body, even though a
// forward declaration is enough for the function's prototype to work properly.
Yes, it's totally possible and one thing I'd like to add is that is generally a good thing to receive the parameter as a pointer to a object of that class since you'll not always want to make a copy of an entire object in memory.
Besides that, you could (and should depending on the case) take the parameter as a pointer to a const object so that the method can access whatever it needs from the object without making a copy of it and without modifying it's members.
I have been programming in C++ for quite some time and I never thought about this until today.
Consider the following code:
struct foo
{
// compiles fine
void bar()
{
a = 1;
my_int_type b;
b = 5;
}
// Just a declaration, this fails to compile, which leads me to assume that
// even though the bar() method is declared and defined all at once, the
// compiler looks/checks-syntax-of the class interface first, and then compiles
// the respective definitions...?
void bar2(my_int_type); // COMPILE ERROR
my_int_type b; // COMPILE ERROR because it comes before the typedef declaration
typedef int my_int_type;
my_int_type a;
void bar3(my_int_type); // compiles fine
};
int main()
{
foo a;
a.bar();
return 0;
}
Is my understanding of why the errors occur (see bar2() comment above) correct/incorrect? Either way, I would appreciate an answer with a simplistic overview of how a single-pass C++ compiler would compile the code given above.
For the most part, a C++ file is parsed top-to-bottom, so entities must be declared before they are used.
In your class, bar2 and b are invalid because they both make use of my_int_type, which has not yet been declared.
One exception to the "top-to-bottom" parsing rule is member functions that are defined inside the definition of their class. When such a member function definition is parsed, it is parsed as if it appeared after the definition of the class. This is why your usage of my_int_type in bar is valid.
Effectively, this:
struct foo
{
void bar()
{
my_int_type b;
}
typedef int my_int_type;
};
is the same as:
struct foo
{
void bar();
typedef int my_int_type;
};
inline void foo::bar()
{
my_int_type b;
}
Compiler just starts to go down in a block. Any symbol which is not familiar to it will be considered as a new symbol which is not defined. This is the scheme behind the function definition or header files.
You can suppose that the compiler first makes a list of definitions so the bar() method should get compiled correctly because the definitions have provided before.
It has a lot to do with visibility. I think your confusion may come from assuming a single pass. Think of class parsing as done in two stages.
Parse class definition.
Parse method implementation.
The advantage to this is we have visibility of the entire class from within class member functions.
Stroustrup states in C++ Language book that order of definitions in the class does not matter.
Indeed:
class C1 {
int foo() { return bar(); } // where is bar() ?
int bar() { return m_count; } // oh, here is bar(). but where is m_count ?
int m_count; // here is m_count. Better late than never !
}
This compiles. Despite misordering. As promised.
So far, so good.
However, this does not compile:
class C2 {
void baz(Inner *p) {} // we were promised that order does not matter
// is Inner defined ?
struct Inner {}; // yes, Inner is define here.
};
This looks a contradiction to Stroustrup's promise of free ordering inside the class. Quoting Stroustrup: "A member function declared within a class can refer to every member of the class as if the class were completely defined before the member function bodies were considered".
Does anybody know a ref to standard clause that allows C1 and disallows C2 ? I am curious why C2 was disallowed while C1 is allowed. Is it compiler bug that contradicts the standard, maybe ?
Note that the following compiles fine (in VS2008):
class C2 {
void baz() { Inner* i = new Inner(); }
struct Inner {};
};
There are two differences between your two examples. The first uses an undeclared symbol inside the body of a function and the second uses an undeclared type in the signature of the function.
I suspect that my example and your first example both work because the function bodies aren't resolved until after the entire class declaration has been parsed. The function signatures have to make sense as soon as they are encountered.
An identifier that denotes a type must be declared prior to use. This has to do with the complicated structure of C++ grammar. The compiler simply cannot parse certain code if it does not know beforehand which identifiers are types.
You are confusing "declarations" with "definitions". The inner class must be declared - if only forward declared - before it can be used.
The order of definition does not matter, but the order of declaration does.
In C++, a declaration means (roughly) stating the "kind" or type of a symbol:
class A; --> A is of kind "class"
void foo(int); --> foo is a function that takes an int and returns nothing
A definition, however, fully defines what the symbol relates to. As in C, a definition happens to be a declaration too.
Finally, to muddy the waters further, for user-declared types, sometimes a definition is required (complete-type) while sometimes a simple declaration is sufficient...
Now, let us revise your issue, I'll illustrate it with a simple example using C++0x:
struct A {
void foo() { ++count; }
void bar(decltype(count) c); // error: 'count' was not declared in this scope
int count;
};
struct B {
void foo() { Inner a; a.foo(); }
void bar(Inner& i); // error: 'Inner' has not been declared
struct Inner { void foo(); };
};
As you can notice, A::foo is parsed correctly, while A::bar is not.
The issue comes from the fact that the compiler "cheats": the methods body are fully analyzed only once the class has been completely parsed. Therefore it is fine to refer to a yet undeclared type/attribute/function in a function body, but it is not fine to refer to it in a function signature (declaration).
You could say that to the compiler, the code is equivalent to:
struct A {
void foo();
void bar(decltype(count) c); // error: 'count' was not declared in this scope
int count;
};
void A::foo() { ++count; }
struct B {
void foo();
void bar(Inner& i); // error: 'Inner' has not been declared
struct Inner { void foo(); };
};
void B::foo() { Inner a; a.foo(); }
Stroustrup sentence is "easy", but not necessarily accurate. For example, using Inner as an attribute requires that it is fully defined (only complete types may be used as non static attributes), which can cause further grief.
struct C {
struct Inner;
Inner foo; // error: field 'foo' has incomplete type
struct Inner { };
};
Though one could argue that Inner foo is a declaration and thus not covered by Stroustrup's quote.
I think the promise of free ordering inside the class is held if you split declaration and definition (into a header and an implementation file). Once you split them, the order really doesn't matter anymore.
Is some one able to explain why header files have something like this?
class foo; // This here?
class bar
{
bar();
};
Do you need an include statement when using this?
Thanks.
The first class foo; is called a forward declaration of the class foo. It simply lets the compiler know that it exists and that it names a class. This makes foo what is called an "incomplete type" (unless the full declaration of foo has already been seen). With an incomplete type, you can declare pointers of that type, but you cannot allocate instances of that type or do anything that requires knowing its size or members.
Such forward declarations are frequently used when two types each may have pointers to each other, in which case both need to be able to express the notion of a pointer to the other type, and so you would have a circular dependency without such a thing. This is needed mostly because C++ uses a single pass mechanism for resolving types; in Java, you can have circular dependencies without forward declarations, because Java uses multiple passes. You may also see forward declarations where the author is under the misguided impression that using forward declarations instead of including the required header reduces compile time; that, of course, is not the case, because you need to include the full declaration (i.e. the header), anyway, and if preprocessor guards are used, then there is basically no difference in compile time.
To answer your question on whether you need the include or not... assuming you only need a partial type, then your header does not need to directly include the header for the type that has been forward declared; however, whoever makes use of your header, when they use your type will need to include the header for the forward declared type, and so you might as well just include the other header.
That's a forward declaration. You need it for example if class bar has a pointer to a foo object, but you don't want to include the whole definition of the foo object immediately.
this is a forward declaration of the class.
In my experience, this is typically done when you have a circular dependency.. for example
in foo.h
--------
#include "bar.h"
class foo
{
public:
foo(bar *bar);
private:
foo *m_foo;
};
and in bar.h
------------
class foo;
class bar
{
public:
void methodFooWillCall();
protected:
std::list<foo *> myFoos;
}
Just curious, why do we need the term forward declaration at all? Isn't a forward declaration simply a declaration (as opposed to a definition)?
class X; // declaration
class X // definition
{
int member;
void function();
};
That's a forward declaration. Consider the following example:
class foo; // you likely need this for the code beneath to compile
class bar {
void smth( foo& );
};
If you haven't included the definition of class foo in such a way that the compiler sees it before compiling the definition of class bar the code will not compile (the compiler will say it doesn't know what foo means) unless you have the forward declaration.
It's a forwards declaration of the class 'foo'. It allows you to declare pointers and references to the class, but not use it (eg. call members or determine its size), because it's not yet defined! It must later be followed up with a full, normal declaration (class foo { ... };).
It's useful for things like declaring two classes which hold pointers to each other, which otherwise would be impossible to set up.
This is called forward declaration. The body of the class foo would be defined at a later part of the file. Forward declaration is done to get around cyclic dependencies: The definition of class Bar requires class Foo and vice versa.
class Bar
{
Foo * foo;
};
class Foo
{
Bar * bar;
};
As you can see, Bar has a reference to Foo and vice versa. If you try to compile this, the compiler will complaint saying that it doesn't know anything about Foo. The solution is to forward declare the class Foo above the Bar (just like you declare the prototype of a function above the main and define its body later).
class Foo; //Tells the compiler that there is a class Foo coming down the line.
class Bar
{
Foo * foo;
};
class Foo
{
Bar * bar;
};
This is called a forward declaration. It is used to make your code aware that the class foo exists. This in turn can be used by the class bar.
It's commonly used to solve circular includes problems. Take this for example
//a.h
#include "b.h"
class A
{
void useB(B obj);
}
and
// b.h
#include "a.h"
class B
{
void useA(A obj);
}
This causes a circular include problem, because a.h includes b.h which in turns includes a.h, to infinity. You can solve this problem by making a forward declaration of each class in each header, like so :
//a.h
class B;
class A
{
void useB(B obj);
}
// b.h
class A;
class B
{
void useA(A obj);
}
Note : Very often when you have a circular include problem, this is indicative of a conception/modelling problem. You should probably ask yourself if your classes are well defined before trying to solve your problem with forward declarations.
Try to think of writing this:
file bar.h:
#include "bar.h"
class Foo
{
Bar* bar_ptr;
}
file foo.h:
#include "foo.h"
class Bar
{
Foo* foo_ptr;
}
This won't work, first due to infinite #include chain, then if you get rid of one of the includes, either Foo won't know what Bar is, or Bar won't know what Foo is.
Try this instead:
class Bar;
class Foo
{
Bar* bar_ptr;
};
file foo.h:
class Foo;
class Bar
{
Foo* foo_ptr;
};