4

I have a struct Tree that is defined inside Class Parser. I have methods defined in Parser that take Tree as input.

void Parser::InputTree(const Tree& input) {
//uses data from Tree
}

Everything seemed to be working fine. But then I needed to use Tree outside the class. So I decided to define struct Tree in a separate header. I included this header in the header file for Parser. While I see no errors in the header file of Parser, the source file shows errors on my Eclipse. Says member declaration not found pointing to method InputTree.

My question is, first off is this the right strategy to define a struct in a separate header? Second, what am I doing wrong? Third, I have some enum types also that I want to use across classes. Where do I define it?

user592748
  • 1,194
  • 3
  • 21
  • 45

3 Answers3

3

Right structure:

parser.h

#ifndef _PARSER_H_
#define _PARSER_H_
#include "tree.h"
class Parser {
   void InputTree(const Tree& input);
};

#endif /*_PARSER_H_*/

parser.cpp

#include "parser.h"
void Parser::InputTree(const Tree& input){
 // use data from Tree
}

tree.h

#ifndef _TREE_H_
#define _TREE_H_

struct Tree {
   //nodes
};
#endif /*_TREE_H_*/

Including parser.h includes tree.h and hence, struct Tree is available in the main compilation unit.

Aniket Inge
  • 25,375
  • 5
  • 50
  • 78
  • sorry, I forgot to add that the I had a template argument for the class. When I defined the struct outside the class, I had use `void Parser::InputTree(const Tree& input) {}`. But thanks for explaining in such detail. – user592748 Mar 10 '13 at 21:05
  • 2
    -1, `_TREE_H_` and `_PARSER_H_` are reserved to the C++ implementation. – robson3.14 Mar 11 '13 at 00:41
  • @AniketInge Macro names with a single leading underscore `_` are reserved by the C++ standard for the implementation (e.g. GCC) to use internally. Likewise, macros with two leading underscores `__` are reserved by the standard for the implementation to use for name mangling. So your `#include` guard macro should just be `TREE_H_`. – villapx Feb 20 '19 at 15:55
3

A simple rule of the thumb I usually follow, is if a custom datatype (i.e. struct, enum, etc.) is used only within a class, I end up defining this datatype within the definition of the class.

But if the same type is required to be used across 2 or more classes (without any parent-child relationship), I end up defining the type either within another header file and usually within a namespace (when the types or related in some fashion).

And yes you could use multiple such namespaces within multiple header files (to group related types), if you feel the need to distinguish them, but I've just show a simpler example using a single namespace:

/* MyNamespace.h */

#ifndef MY_NAMESPACE_H
#define MY_NAMESPACE_H

namespace MyNamespace {
    struct Tree {
        int a;
        char b;
    };

    enum SomeEnum {
        VALUE_0 = 0,
        VALUE_1 = 1,
        VALUE_2 = 2
    };
}

#endif

/* Parser.h */

#ifndef PARSER_H
#define PARSER_H

#include "MyNamespace.h"

class Parser
{
public:
    void InputTree(const MyNamespace::Tree& input);
};

#endif

/* Parser.cpp */

#include "Parser.h"

void Parser::InputTree(const MyNamespace::Tree& input)
{

}
Tuxdude
  • 47,485
  • 15
  • 109
  • 110
  • `_MY_NAMESPACE_H_` and `_PARSER_H_` are identifiers reserved to the C++ implementation. – robson3.14 Mar 11 '13 at 00:44
  • @robson3.14 - can you provide some reference to back that fact ? – Tuxdude Mar 11 '13 at 00:53
  • 2
    17.6.4.3.2 [global.names] Each name that contains a double underscore _ _ or begins with an underscore followed by an uppercase letter (2.12) is reserved to the implementation for any use. – robson3.14 Mar 11 '13 at 01:00
  • I was aware of the double underscore, but not the other. Good catch :) – Tuxdude Mar 11 '13 at 01:01
2

Yes, it is a correct strategy to define the struct in a separate header file.

What you are doing wrong is hard to say without more input - but it probably has to do with includes, include-guards or namespace mismatches.

And finally, you should declare the enums in another header file, with proper include guards.

fredrik
  • 6,483
  • 3
  • 35
  • 45