C++ 如何最好地使用#include来防止多重定义错误?

C++ 如何最好地使用#include来防止多重定义错误?,c++,makefile,include,include-guards,multiple-definition-error,C++,Makefile,Include,Include Guards,Multiple Definition Error,在现有项目中实现三个文件(tree.h、tree.cpp和node.h)时,我在parser.h和parser.cpp文件中引用它们时遇到了“多重定义”错误。我正在使用include-guard来防止多重包含,但我认为这并不是我想要的。我也在使用普通的C++99并在Linux机器上编译,我无法控制它 getNode()是用node.h中的node\u t结构定义的,它们都需要可用于parser.cpp、parser.h、tree.cpp和tree.h 生成文件 我尝试将node.h和token.

在现有项目中实现三个文件(tree.h、tree.cpp和node.h)时,我在parser.h和parser.cpp文件中引用它们时遇到了“多重定义”错误。我正在使用include-guard来防止多重包含,但我认为这并不是我想要的。我也在使用普通的C++99并在Linux机器上编译,我无法控制它

getNode()是用node.h中的node\u t结构定义的,它们都需要可用于parser.cpp、parser.h、tree.cpp和tree.h

生成文件 我尝试将node.h和token.h添加到OBJFILES中,但这只会导致在我进行清理时删除这些文件

node.h

#include <stdio.h> 
#include <stdlib.h> 
#include <string>

#include "token.h"

#ifndef NODE_H_
#define NODE_H_

struct node_t
{
    std::string label;
    Token* token1;
    Token* token2;
    //struct node_t *left;
    //struct node_t *right;
    struct node_t *child;
};

node_t* getNode( std::string functionName )
{
    // Create the node
    node_t* node = (struct node_t*)malloc(sizeof(struct node_t)); 
    node->label = functionName;
    node->child = NULL;
    node->token1 = NULL;
    node->token2 = NULL;

    return node;
}

#endif

#包括
#包括
#包括
#包括“token.h”
#ifndef节点_
#定义节点_
结构节点
{
字符串标签;
令牌*token1;
令牌*token2;
//结构节点_t*左;
//结构节点(右);
结构节点_t*子节点;
};
node_t*getNode(std::string functionName)
{
//创建节点
node_t*node=(结构节点_t*)malloc(sizeof(结构节点_t));
节点->标签=函数名;
节点->子节点=NULL;
节点->标记1=NULL;
node->token2=NULL;
返回节点;
}
#恩迪夫
我把我所有的文件和它们的#include语句和标题保护都拿了出来,并模拟了一张所有发生的事情的图表。

这几乎不是makefile的问题。任何一个cpp文件中的模板类定义?要优化编译时间,请将所有包含移动到包含保护中。错误似乎位于
node.h
中。我的期望是您已经在头文件中定义了一个名为
getNode(std::string)
的自由函数,并且多个翻译单元包含此头文件,导致违反ODRY。如果您将定义(函数或变量,而不是类型)放入头文件中,您将需要提供一个或至少是
node.h的代码,使用
inline
关键字。当头包含在多个编译单元中时,Include-guard不适用,这是您的情况。它们只是防止在一次编译中多次重新处理相同的头。
CC = g++
CFLAGS = -g -Wall -Wno-unused-variable
CXXFLAGS = -g

OBJFILES = main.o scanner.o parser.o tree.o 
TARGET = frontend

all: $(TARGET)


$(TARGET): $(OBJFILES)
    $(CC) $(CFLAGS) -o $(TARGET) $(OBJFILES)


.PHONY: clean
    
clean:
    rm -f $(OBJFILES) $(TARGET) *~
#include <stdio.h> 
#include <stdlib.h> 
#include <string>

#include "token.h"

#ifndef NODE_H_
#define NODE_H_

struct node_t
{
    std::string label;
    Token* token1;
    Token* token2;
    //struct node_t *left;
    //struct node_t *right;
    struct node_t *child;
};

node_t* getNode( std::string functionName )
{
    // Create the node
    node_t* node = (struct node_t*)malloc(sizeof(struct node_t)); 
    node->label = functionName;
    node->child = NULL;
    node->token1 = NULL;
    node->token2 = NULL;

    return node;
}

#endif