链接时为什么会出现多重定义错误?

时间:2012-03-31 20:46:11

标签: c++ ubuntu linker gcc4.4

我使用这两个文件herehere

我在两个单独的文件中创建了一个类:

modul1.h

#ifndef MODUL1_H
#define MODUL1_H

#include <iostream>
#include <fstream>

#include "easylogger.h"

class Modul1
{
    public:
        Modul1(std::string name);
    protected:
    private:
        easylogger::Logger *log;
};

#endif // MODUL1_H

和modul1.cpp

#include "modul1.h"

Modul1::Modul1(std::string name):log(new easylogger::Logger(name))
{
    //ctor
    //std::ofstream *f = new std::ofstream(name.c_str(), std::ios_base::app);
    //log->Stream(*f);
    //log->Level(easylogger::LEVEL_DEBUG);
    //LOG_DEBUG(*log, "ctor ende!");
}

现在我想在另一个文件(main.cpp)中使用这个类:

#include "modul1.h"

int main()
{
    std::cout << "Hello world!" << std::endl;
    Modul1 mod1("test.log");
    return 0;
}

当我使用以下Makefile编译它时,我得到了“...的多重定义”错误:

  

g ++ main.o modul1.o -o main modul1.o:在函数中   easylogger::Logger::Format(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)': modul1.cpp:(.text+0x0): multiple definition of easylogger :: Logger :: Format(std :: basic_string,std :: allocator&gt; const&amp;)'   main.o:main.cpp :(。text + 0x0):首先在这里定义modul1.o:在函数中   easylogger::Logger::WriteLog(easylogger::LogLevel, easylogger::Logger*, char const*, unsigned int, char const*, char const*)': modul1.cpp:(.text+0x2a): multiple definition of easylogger ::记录器:: WRITELOG(easylogger ::日志级别   easylogger :: Logger *,char const *,unsigned int,char const *,char   const *)'main.o:main.cpp :(。text + 0x2a):首先在这里定义collect2:ld   返回1退出状态

(起初我用code :: blocks编译它并得到了相同的错误)

如何修改我的Modul1以避免出现此链接错误?我认为这不重要,但我使用的是一些带有g ++ 4.4.3的Ubuntu 64bit

生成文件:

CC=g++
CFLAGS=-c -Wall

all: log_test

log_test: main.o easylogger.h modul1.o
    $(CC) main.o modul1.o -o main

main.o: main.cpp modul1.h
    $(CC) $(CFLAGS) main.cpp

modul1.o: modul1.cpp modul1.h
    $(CC) $(CFLAGS) modul1.cpp

2 个答案:

答案 0 :(得分:4)

您在两个翻译单元中都包含“easylogger-impl.h”。 easylogger-impl.h中有函数定义。因此,您有多个函数定义。

一个定义规则表明您必须只有一个对象或函数的定义。

您可以将所有easylogger-impl函数标记为inline,或者确保它们只出现在一个翻译单元中来解决此问题。

答案 1 :(得分:4)

你构建它的方式,easylogger.h(以及因此easylogger-inl.h)被包含两次,一次用于modul1.h,一次用于main.cpp

你对它的使用是错误的。但你可以做到这一点,使它工作:

在modul1.h中(删除#include“easylogger.h”)并使它看起来像这样

#ifndef MODUL1_H
#define MODUL1_H

#include <iostream>
#include <fstream>
//#include "easylogger.h"

namespace easylogger { class Logger; };

class Modul1
{
    public:
        Modul1(std::string name);
    protected:
    private:
        easylogger::Logger *log;
};

#endif // MODUL1_H

和modul1.cpp,包含真实的东西

#include "modul1.h"
#include "easylogger.h"

Modul1::Modul1(std::string name):log(new easylogger::Logger(name))
{
    //ctor
    //std::ofstream *f = new std::ofstream(name.c_str(), std::ios_base::app);
    //log->Stream(*f);
    //log->Level(easylogger::LEVEL_DEBUG);
    //LOG_DEBUG(*log, "ctor ende!");
}
祝你好运!