开发者

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* or Vertex&, 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
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜