c++ 类声明和定义分离后出现的问题


我用c++写了一个小型的project,main.cpp中,需要包括三个头文件,lexer.h,parser.h,interpreter.h
这三个头文件分别有一个同名的类的声明和实现,编译和运行都是成功的,但现在我想把类的声明和实现分开,比如lexer类的声明在lexer.h,实现在lexer.cpp,打算在makefile中先分别编译再链接,但分离后会出现一些函数和变量多次声明的error,我想知道应该怎么解决?

补充以下,代码长度略长,只贴出部分:
makefile:


 srcpath = src
.PHONY: all clean
all: main
main: $(srcpath)/main.o $(srcpath)/lexer.o
    g++ -o main $(srcpath)/main.o $(srcpath)/lexer.o
main.o: $(srcpath)/main.cpp
    g++ -c $(srcpath)/main.cpp
lexer.o: $(srcpath)/lexer.cpp
    g++ -c $(srcpath)/lexer.cpp
clean:
    rm -rf main

在这里我只把lexer.h拆成了lexer.h(类声明)和lexer.cpp(类实现)。
报错信息如下:
src/lexer.o:(.bss+0x0): MAX_NUM'被多次定义 src/main.o:(.bss+0x0):第一次在此定义 src/lexer.o:在函数‘getString(int)’中: lexer.cpp:(.text+0x0): getString(int)'被多次定义
src/main.o:main.cpp:(.text+0x0):第一次在此定义
src/lexer.o:在函数‘compNums(Token, Token, int)’中:
……
其中报错为多次定义的这些变量/函数,我定义在token.h中,这个头文件在lexer.h和parser.h都有包含,每个头文件我都有声明防止重复包括的宏,代码如同:


 #ifndef LEXER_H
#define LEXER_H
//my code
#endif

谢谢!

makefile C++ g++

桌面小助手 11 years, 5 months ago

你最好把代码贴出来,不知道你定义的比如MAX_NUM是不是const有类型的,const有类型的话反正貌似多次包含会报重定义错误的,就算你加上了开头的防止重复包含也没用(至少我的代码都是如此),如果是宏定义的话一般不会报重定义的。。。。

kavern answered 11 years, 5 months ago

我怀疑你的.cpp文件写法有问题,都是包含.h文件,没有包含.cpp文件的,否则要.h文件干什么。而且按照正常的写法,包含.cpp文件编译会报错,因为类的定义在.h文件中,.cpp文件不包含类的定义。建议你把.cpp文件代码挂上来,问题不是包含.cpp文件这么简单。

kkkkuso answered 11 years, 5 months ago

问题解决了,很抱歉没有把代码贴出来给大家,我的解决方法是把声明和实现拆分后,让原来包含.h的改为包含.cpp这样就好了

kasim28 answered 11 years, 5 months ago

MAX_NUM getString(int) 这个两个是定义在token.h中吗,它俩的代码贴出来。
把各源文件对头文件的包含关系贴出来。

感觉是你在头文件中定义的变量与函数,这个头文件又被多个源文件包含,链接就出问题了。

killer7 answered 11 years, 5 months ago

以下描述仅个人理解...望轻拍

局部变量函数:

如果仅仅是 classA.cpp 中要用,那直接定义到 classA.cpp 头部;

全局变量函数:

你可以另外新建两文件: global.cpp/global.h
global.cpp 中定义,然后在 global.h extern 导出,
然后在 classA.cpp classB.cpp 头部 #include "global.h" 即可使用上述变量或函数。

需要交叉包含的 XXX.h 文件中直接定义变量函数会出问题

我以前在使用VC6.0时,就被弄惨了,在VS2012中还好一点,新建类头文件顶部默认有一行: #pragma once

图片描述

Bandage answered 11 years, 5 months ago

Your Answer