Proper way to manage C++ include directives
I'm a little confused about how C++ handles includes.
I have something like:
typedef struct {
//struct fields
} Vertex;
#include "GenericObject.h"
Now in GenericObject.h I have:
class GenericObject {
public:
Vertex* vertices;
}
When I try to compile, the compiler says:
ISO C++ forbids declaration of 'Vertex' with no type
How do I get GenericObject.h to know about Vertex?
I was under the impression that anything defined before an #include, was available in the included files.
开发者_开发知识库And lastly, could you give me some tips on how to correctly use #include without introducing too much redundancy or circular includes.
Thanks.
Two things, first you want it to just be...
struct Vertex
{
//struct fields
};
That is a properly defined struct in C++. Now you either need to include Vertex.h, or what ever file contains the vertex struct, in your generic object header,
#include "Vertex.h"
class GenericObject {
public:
Vertex* vertices;
};
or forward declare it as so...
struct Vertex;
class GenericObject {
public:
Vertex* vertices;
};
don't #include "GenericObject.h" from "Vertex.h".
I was under the impression that anything defined before an #include, was available in the included files.
Yes (so I'm not sure what's going on your code), but please don't rely on this!. A header should be self-contained, and should absolutely not rely on what's been included in other files before it, outside of its "scope".
(As an aside, this rule applies also for using
declarations: do not write using namespace std
in your header A, as you may find that you end up accidentally relying on that being present from your headers B and C that include header A!)
Where you use
Vertex
,#include
the header that defines it.Where you use merely
Vertex*
orVertex&
, you can usually just forward-declare the type:struct Vertex;
. This helps to avoid circular dependencies.
To answer your second question about circular includes. This is how most people do it. For example to include the header.h
#ifndef HEADER_H
#define HEADER_H
//you code here
#endif
One way around this is to "forward-declare" the vertex structure:
//
// GenericObject.h
//
struct Vertex;
class GenericObject {
{
public:
Vertex *vertices;
};
Note at this point Vertex is an "incomplete type", so anything that has to take its size or access its members will not work. You can declare pointers to them, though.
At the risk of sounding pedantic, you should put your #include
directives at the top of the translation unit. Then you can have:
// File vertex.h
#ifndef VERTEX_H
#define VERTEX_H
struct Vertex { ... };
#endif
And
// File gobject.h
#ifndef GOBJECT_H
#define GOBJECT_H
#include "vertex.h"
class GObject { ... }; // Use Vertex structures here
#endif
Alternatively, as pointed out, you can declare the Vertex
structure in advance:
// File gobject.h
#ifndef GOBJECT_H
#define GOBJECT_H
struct Vertex; // Declaration of a struct named Vertex
class GObject { ... }; // Use Vertex structures here
#endif
精彩评论