IT技术博客大学习 共学习 共进步
全部 移动开发 后端 数据库 AI 算法 安全 DevOps 前端 设计 开发者

有关最近GCC编译出现的firstdefine问题

Vimer 2010-04-27 23:29:02 累计浏览 2,780 次
本机暂存

最近在编译项目的时候,出现的first define here的错误。仔细排查了.h文件的define定义等,最后发现是自己定义类的时候写法有问题。因为这个问题浪费了很长时间,所以特别记在这里。
做测试如下:
新建一个目录firstdef,在其中创建文件firstdef.h,代码如下:

#ifndef _FIRSTDEF_H_
#define _FIRSTDEF_H_
#include <iostream>
#include <string>
#include <vector>
#include <map>
using namespace std;
class CFirstDef
{
    public:
        void Show();
        void Error();
        void Test()
        {
            printf("Test\n");
        }
};
void Show()
{
    printf("OK\n");
}
#endif

对应建立firstdef.cpp,代码如下:

#include "firstdef.h"
void CFirstDef::Error()
{
    printf("Error\n");
}

对应编译成lib库的makefile如下:

SRC_DIR= ./
OBJ_DIR= ./
LIB_DIR= ./
OBJ_EXT= .o
CXXSRC_EXT= .cpp
CSRC_EXT= .c
LIB_EXT= .a
H_EXT= .h
OBJECTS = $(OBJ_DIR)firstdef$(OBJ_EXT)
LIB_TARGET = $(LIB_DIR)libfirstdef$(LIB_EXT)
$(OBJ_DIR)%$(OBJ_EXT): $(SRC_DIR)%$(CXXSRC_EXT)
    @echo
    @echo "Compiling $< ==> $@..."
    $(CXX) $(INC) $(C_FLAGS) -c $< -o $@
$(OBJ_DIR)%$(OBJ_EXT): $(SRC_DIR)%$(CSRC_EXT)
    @echo
    @echo "Compiling $< ==> $@..."
    $(CC)  $(INC) $(C_FLAGS) -c $< -o $@
all:$(LIB_TARGET)
$(LIB_TARGET): $(OBJECTS)
all: $(OBJECTS)
    @echo
    $(AR) rc $(LIB_TARGET) $(OBJECTS)
    @echo "ok"
clean:
    rm -f $(LIB_TARGET) $(OBJECTS)

编译结果如下:

lib

之后在与firstdef目录平级的地方创建文件test.cpp:

#include <iostream>
#include <string>
#include <vector>
#include <map>
#include "firstdef.h"
using namespace std;
int main(int argc, const char *argv[])
{
    CFirstDef t;
    t.Show();
    t.Error();
    return 0;
}

makefile如下:

CXX = g++
TARGET = test
C_FLAGS += -g -Wall
LIB_FLAGS = 
INC=-I./firstdef
LIB=-L./firstdef -lfirstdef
all: $(TARGET)
test:  test.o
    $(CXX) -o $@ $^  $(LIB_FLAGS) $(LIB) $(C_FLAGS)
.cpp.o:
    $(CXX) -c -o $*.o $(INC) $(C_FLAGS) $*.cpp
.cc.o:
    $(CXX) -c -o $*.o $(INC) $(C_FLAGS) $*.cc

clean:
    -rm -f *.o $(TARGET)

编译结果如下:

exe

由此可见,对比Show和Test函数可以发现,Show报错而Test却没有报错。
对于公司同事说如果不用lib而是直接编译.o的话就不会出错,我单独测试了一下,makefile如下:

CXX = g++
TARGET = test
C_FLAGS += -g -Wall
LIB_FLAGS = 
INC=-I./firstdef
#LIB=-L./firstdef -lfirstdef
all: $(TARGET)
test:  test.o ./firstdef/firstdef.o
    $(CXX) -o $@ $^  $(LIB_FLAGS) $(LIB) $(C_FLAGS)
.cpp.o:
    $(CXX) -c -o $*.o $(INC) $(C_FLAGS) $*.cpp
.cc.o:
    $(CXX) -c -o $*.o $(INC) $(C_FLAGS) $*.cc

clean:
    -rm -f *.o $(TARGET)

编译结果如下:

exe2

而至于还有公司同事提到如果把Show设置为内联是否就没有问题,我也测试了一下,错误依旧。

有不少的教程都会将函数的实现写在头文件中,如此看来,还真是会给读者们造成许多误读啊。

另附:源代码下载,需要的朋友可以自己研究一下。

以上代码均在windows下g++ 3.4.5编译通过。

同分类推荐文章

  1. 等了十年的 Go 链式管道,终于来了:seq 让你像写 Scala 一样写 Go (2026-06-25 18:38:18)
  2. Go 实验特性详解 (2026-06-21 10:05:27)
  3. amd64 微架构级别对 Go 程序性能提升多少? (2026-06-21 09:38:49)

查看更多 后端 文章 →

建议继续学习

  1. 如何学好C++语言 (累计阅读 10,450)
  2. Emacs配置C/C++-mode的代码智能提示和自动补全 (累计阅读 10,414)
  3. colortail,让 tail 命令绚丽起来 (累计阅读 10,260)
  4. 在C++中实现foreach循环,比for_each更简洁! (累计阅读 9,500)
  5. 几个内存相关面试题(c/c++) (累计阅读 9,447)
  6. 关于使用STL的红黑树map还是hashmap的问题 (累计阅读 8,876)
  7. 浅析C++多线程内存模型 (累计阅读 8,803)
  8. C++ 多线程编程总结 (累计阅读 8,098)
  9. 使用gdb调试运行时的程序小技巧 (累计阅读 7,209)
  10. 在C++里写一个不能被继承的类 (累计阅读 6,581)