2013-03-10 82 views
4

我有一个struct TreeClass Parser内定义。我有Parser中定义的方法,其中Tree作为输入。结构在单独的头文件导致C++中的问题

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

一切似乎工作正常。但之后我需要在课外使用Tree。所以我决定在一个单独的头文件中定义struct Tree。我将这个头文件包含在Parser的头文件中。虽然我在Parser的头文件中看不到任何错误,但源文件在我的Eclipse上显示错误。说没有发现成员声明指向方法InputTree

我的问题是,首先是这是一个正确的策略来定义一个单独的头结构?其次,我做错了什么?第三,我也有一些enum类型,我想跨类使用。我在哪里定义它?

回答

3

右结构:

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_*/ 

包括parser.h包括tree.h,因此,struct Tree是在主编译单元可用。

+0

对不起,我忘了补充一点,我有一个模板参数为班级。当我在类之外定义结构时,我使用了'void Parser :: InputTree(const Tree &input){}'。不过谢谢你这样详细解释。 – user592748 2013-03-10 21:05:21

+1

-1,'_TREE_H_'和'_PARSER_H_'保留给C++实现。 – 2013-03-11 00:41:26

+0

@ robson3.14吧? – 2013-03-11 06:24:01

2

是的,在单独的头文件中定义结构是一个正确的策略。

如果没有更多的输入,你做错了很难说 - 但它可能与include,include-guard或命名空间不匹配有关。

最后,你应该在另一个头文件中声明枚举,并使用适当的包含守护进程。

3

我通常遵循的一个简单的规则是,如果仅在类中使用自定义数据类型(即结构体,枚举等),我最终会在类的定义中定义此数据类型。

但是,如果需要跨2个或更多的类(没有任何父 - 子关系)使用相同的类型,我最终在另一个头文件中定义类型,通常在命名空间内(类型或相关以某种方式)。

是的,你可以使用中的多个头文件的多个这样的命名空间(将相关类型),如果你觉得有必要区分它们,但我一直在使用一个命名空间只是显示一个简单的例子:

/* 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) 
{ 

} 
+0

'_MY_NAMESPACE_H_'和'_PARSER_H_'是保留给C++实现的标识符。 – 2013-03-11 00:44:55

+0

@ robson3.14 - 你能否提供一些参考来回避这个事实? – Tuxdude 2013-03-11 00:53:17

+2

17.6.4.3.2 [global.names] 包含双下划线_ _的每个名称或以下划线开头且后面带有大写字母 的字母(2.12)保留给实施用于任何用途。 – 2013-03-11 01:00:10