include in main and class body returns 多重定义错误
Include in main and class body returns multiple definition error
我正在尝试编译一个包含 class header 的主函数。主函数以及 class cxx 文件使用一个名为 "SayHello" 的辅助函数。但是,如果我在主文件中包含辅助文件 "Hello.h" 和 class cxx 文件,则会出现多重定义错误。我在下面放了最少的例子。你能帮帮我吗?
干杯,
安德烈亚斯
Main.cxx:
#include "Class.h"
#include "Hello.h"
int main(int argc, char **argv){
SayHello();
return 0;
}
Class.h
#ifndef CLASS_H
#define CLASS_H
class Class {
public:
Class();
~Class();
};
#endif
Class.cxx
#include "Class.h"
// #include "Hello.h" //with this it breaks!
Class::Class(){
// SayHello(); //with this it breaks!
}
Hello.h
#ifndef HELLO_C
#define HELLO_C
#include <iostream>
void SayHello(){
std::cout<<"hello!"<<std::endl;
}
#endif
我的生成文件:
# Compiler
CXX = $(shell root-config --cxx)
# Compiler flags
ROOTCFLAGS := $(shell root-config --cflags)
ROOTLIBS := $(shell root-config --libs)
CFLAGS = -Wall ${ROOTCFLAGS} ${INCLUDE_PATH}
LFLAGS = -O3 ${ROOTLIBS} -lHistPainter
# Targets
EXE = Main
OBJS = Main.o Class.o
# Processing
# -------------------------------------
all: ${OBJS} ${EXE}
@echo "Done"
${EXE}: ${OBJS}
@echo "Making executable $(notdir $@)"
${CXX} ${CFLAGS} ${OBJS} ${LFLAGS} -o $@
${EXE}.o: ./${EXE}.cxx
@echo "Compiling $(notdir $<)"
${CXX} $(CFLAGS) -c $< -o $@
%.o: ./%.cxx ./%.h
@echo "Compiling $(notdir $<)"
${CXX} $(CFLAGS) -c $< -o $@
clean:
@echo "Cleaning"
@rm -f ./Main
@rm -f ./Main_cxx.so
@rm -f ./Main_cxx.d
@rm -f ./*.o
@rm -f ./*ACLiC_dict_rdict.pcm
您将 SayHello
函数的定义放在 header 文件中。这是错误的。
由于您将此 header 文件包含在两个不同的文件中,因此该定义在两个不同的文件中被编译了两次,并且您的链接器最终在末尾看到了同一函数的两个定义。
这就是为什么您的 header 文件 Hello.h 应该只包含函数的原型:
#ifndef HELLO_C
#define HELLO_C
void SayHello();
#endif
虽然定义应该在单独的 Hello.cxx 文件中:
#include <iostream>
#include "Hello.h"
void SayHello(){
std::cout<<"hello!"<<std::endl;
}
当然,不要忘记将这个新文件添加到您的 Makefile 中:
OBJS = Main.o Class.o Hello.o
更新:
正如 Rene 所说,您也可以通过在 header 中添加 inline
关键字来简单地将您的函数声明为内联函数。它会让你的编译器在每次调用此函数时复制整个函数内容,而不是进行函数调用。
这通常用于非常短的函数,通常是 getter 和 setter 函数。由于您的函数只是一个“Hello”打印,因此将其设为内联函数可能不是一个坏习惯。
但要小心:代码中过多的内联函数会减慢编译速度,并增加依赖性。例如,如果您内联 SayHello
函数,任何包含 "Hello.h"
的文件也应包含 <iostream>
。
我正在尝试编译一个包含 class header 的主函数。主函数以及 class cxx 文件使用一个名为 "SayHello" 的辅助函数。但是,如果我在主文件中包含辅助文件 "Hello.h" 和 class cxx 文件,则会出现多重定义错误。我在下面放了最少的例子。你能帮帮我吗?
干杯, 安德烈亚斯
Main.cxx:
#include "Class.h"
#include "Hello.h"
int main(int argc, char **argv){
SayHello();
return 0;
}
Class.h
#ifndef CLASS_H
#define CLASS_H
class Class {
public:
Class();
~Class();
};
#endif
Class.cxx
#include "Class.h"
// #include "Hello.h" //with this it breaks!
Class::Class(){
// SayHello(); //with this it breaks!
}
Hello.h
#ifndef HELLO_C
#define HELLO_C
#include <iostream>
void SayHello(){
std::cout<<"hello!"<<std::endl;
}
#endif
我的生成文件:
# Compiler
CXX = $(shell root-config --cxx)
# Compiler flags
ROOTCFLAGS := $(shell root-config --cflags)
ROOTLIBS := $(shell root-config --libs)
CFLAGS = -Wall ${ROOTCFLAGS} ${INCLUDE_PATH}
LFLAGS = -O3 ${ROOTLIBS} -lHistPainter
# Targets
EXE = Main
OBJS = Main.o Class.o
# Processing
# -------------------------------------
all: ${OBJS} ${EXE}
@echo "Done"
${EXE}: ${OBJS}
@echo "Making executable $(notdir $@)"
${CXX} ${CFLAGS} ${OBJS} ${LFLAGS} -o $@
${EXE}.o: ./${EXE}.cxx
@echo "Compiling $(notdir $<)"
${CXX} $(CFLAGS) -c $< -o $@
%.o: ./%.cxx ./%.h
@echo "Compiling $(notdir $<)"
${CXX} $(CFLAGS) -c $< -o $@
clean:
@echo "Cleaning"
@rm -f ./Main
@rm -f ./Main_cxx.so
@rm -f ./Main_cxx.d
@rm -f ./*.o
@rm -f ./*ACLiC_dict_rdict.pcm
您将 SayHello
函数的定义放在 header 文件中。这是错误的。
由于您将此 header 文件包含在两个不同的文件中,因此该定义在两个不同的文件中被编译了两次,并且您的链接器最终在末尾看到了同一函数的两个定义。
这就是为什么您的 header 文件 Hello.h 应该只包含函数的原型:
#ifndef HELLO_C
#define HELLO_C
void SayHello();
#endif
虽然定义应该在单独的 Hello.cxx 文件中:
#include <iostream>
#include "Hello.h"
void SayHello(){
std::cout<<"hello!"<<std::endl;
}
当然,不要忘记将这个新文件添加到您的 Makefile 中:
OBJS = Main.o Class.o Hello.o
更新:
正如 Rene 所说,您也可以通过在 header 中添加 inline
关键字来简单地将您的函数声明为内联函数。它会让你的编译器在每次调用此函数时复制整个函数内容,而不是进行函数调用。
这通常用于非常短的函数,通常是 getter 和 setter 函数。由于您的函数只是一个“Hello”打印,因此将其设为内联函数可能不是一个坏习惯。
但要小心:代码中过多的内联函数会减慢编译速度,并增加依赖性。例如,如果您内联 SayHello
函数,任何包含 "Hello.h"
的文件也应包含 <iostream>
。