structs declaration and definition

I maybe asked this already somewhere in past but I cannot recall it.

Where should be structs defined in header or in cpp file? Now I have found project where all structs are defined in cpp file but not declared. I think it would be more clear to define them in header... But is this really definition, when there are no values passed in it? I use Visual Studio C++ 2010, so I cannot set defaults for the struct.
Last edited on
Please alaborate. Some examples would be nice. It might be that you mixing up "declaration" and "definition".

If you define something in header you are going to have multiple definition problem if that header included more that in one compilation unit. (aside from very special cases)
This is my header:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
#ifndef VIEW_MAPVIEW_H
#define VIEW_MAPVIEW_H
#define WIN32_LEAN_AND_MEAN
#define OEMRESOURCE	//OCR_NORMAL
#include <windows.h>

const char MapClass[] = "AOKTSMapView";

/**
 * Creates a mapview window with specified owner and at specified position. The
 * window will be left hidden; it is the caller's responsibility to call
 * ShowWindow().
 */
HWND CreateMapView(HWND owner, int x, int y, class Scenario * scenario);

enum Map_Msgs
{
	// In
	MAP_Close = WM_APP + 0x150,
	MAP_HighlightPoint,	//x, y
	MAP_UnhighlightPoint, //x, y (see MAP_UNHIGHLIGHT_ALL below)
	MAP_Reset,
	/* wParam: non-zero if the mapview should resize to fit the current scen
	 * lParam: unused.
	 */

	// Out
	MAP_Click = WM_APP + 0x200,
	/*	wParam: unused
		lParam: MAKELPARAM(x, y) //map coordinates
		*/
	MAP_SELECT_START, // Ctrl+left mouse button click initiated mouse drag
	MAP_SELECT_END // mouse button has been released, the area coordinates will be saved
};

#define MAP_UNHIGHLIGHT_ALL 0xFFFFFFFF

inline void MapView_Reset(HWND mapview, bool resize = false)
{
	SendMessageW(mapview, MAP_Reset, resize, 0);
}

////////////////////////////////////////////////////////////////////////////////
//  Map selection structure definition  //
////////////////////////////////////////////////////////////////////////////////

#define MAP_SELECTION_MAX_COUNT 256
#define MAX_GROUP 10

/*
type: 
	-1 - exclude RECT
	-2 - exclude COORD
	0 - not defined
	1  - include RECT
	2  - include COORD
groupID:
	0 - common (default)
	max. value 9, the value should be defined by user pressing num key
groupDefined:
	(indexed from 0)
	0 - not defined
	1 - defined (group exists)
groups:
	groups keeps lists of selIDs for every group
	every group can have sizeof(int)*MAP_SELECTION_MAX_COUNT bytes
	if the value is smaller than 0 then it is not defined (end of selID list)
	if the value is 0 or greater then it is id of the selection
*/

typedef struct {
  int selID;
  char groupID; 
  RECT coord;
} MAPSEL_GENERAL;

typedef struct {
  int selID;
  char groupID; 
} MAPSEL_GROUPS;

// Use of data in this struct is not ideal
// There will be at least 3/4 of the buffer not used!
typedef struct {
  int sels_count; // count of selections user did in map viewer
  char groupDefined [MAX_GROUP];
  MAPSEL_GROUPS groups [MAX_GROUP][MAP_SELECTION_MAX_COUNT];
  // the type specifies which type is defined for the particular selID
  char type[MAP_SELECTION_MAX_COUNT]; // previous selection type
  MAPSEL_GENERAL include_rect[MAP_SELECTION_MAX_COUNT];
  MAPSEL_GENERAL exclude_rect[MAP_SELECTION_MAX_COUNT];
  MAPSEL_GENERAL include_coord[MAP_SELECTION_MAX_COUNT];
  MAPSEL_GENERAL exclude_coord[MAP_SELECTION_MAX_COUNT];
} MAPSEL_STRUCT;

#endif	 // VIEW_MAPVIEW_H 


This is start of cpp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
int norotate = 1;

#include "mapview.h"

#include "../util/settings.h"
#include "../model/scen.h"

#include "../util/winugly.h"
#include <math.h>	//all the trig functions
#include <stdio.h>
#include <climits>

// Brushes (created with window)
HBRUSH *tBrushes;
HBRUSH *pBrushes;
HBRUSH bWhite;

// The mapview window actually draws the map to a bitmap in memory
// and then blits the bitmap to the client area when needed. This
// saves processing when resizing and scrolling the window.

struct Highlight
{
	short x, y;
	struct Highlight *prev, *next;
};

struct MapViewData
{
	Scenario * scen;
	HDC copydc;	//DC used for saving what's under a highlight, etc.
	HBITMAP mapbmp;//bitmap storage for map
	int bmpsize;
	int offsetx, offsety;
	int scrollMaxX, scrollMaxY;
	HWND statusbar;
	Highlight *highlights;	//LL of the highlighted points
} data;

// Handles negatives as well
inline int myround(double n)
{
	return int((n >= 0.0) ? n + 0.5 : n - 0.5);
}

#define pi 3.1415926536

const double sin45 = sin(pi / 4);
const double nsin45 = sin(-pi / 4);
const double root2 = sqrt(2.0);


The structs in cpp are not mine (I did not write them), I create only the structs in header.
Last edited on
If the struct is used in multiple C++ files then declare it in the header. If it is limited to one C++ file then putting in that file is fine.
As MiNipaa stated, you're confusing definition and declaration. What you have in your header file are declarations, not definitions. A declaration tells the compiler what an object looks like. A definition allocates space for the object.

Since you mention .cpp files, I'm assuming you're using C++. typedef is not needed in C++. Typedefs are a holdover from C. Simply declare your struct as:
1
2
3
4
5
struct MAPSEL_GENERAL
{ int selID;
  char groupID; 
  RECT coord;
};

In C++, a structure tag (MAPSEL_GENERAL) is a unique type.
Actually there is a single definition in .h file and that is one of the exceptions to ODR: inline functions. Also strictly saying structs are defined in header, this is another exception to ODR: class can be defined in different compilation units (this doesn't extends on non-inline member functions)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
struct foo; //Forward declaration, ok in headers

struct foo //Class definition, ok in headers
{
    int x;
    void y() {} //Inline member definition, ok in headers
    void z(); //Member function declaration, ok in headers
};

void foo::z()
{} //Member function definition, NOT OK in headers

void a(); //function declaration, ok in headers

void a()
{} //Function definition, NOT OK in headers

inline void b() {} //inline function definition, OK in headers 

Structs should be defined in headers, unless they are local to specific file — a special occasion, prefer to define them in header, you can easily move them to implementation file later if needed.

Note that class definitions, [member] function definitions and variable definition are governed by different rules in relation to ODR.
Topic archived. No new replies allowed.