Почему я получаю многократную ошибку при связывании? - PullRequest
5 голосов
/ 01 апреля 2012

Я использую эти два файла здесь и здесь .

Я создал класс в двух отдельных файлах:

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:: Формат (std :: basic_string, std :: allocator> const &) '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 :: Logger :: WriteLog(easylogger :: LogLevel, easylogger :: Logger *, char const *, unsigned int, char const *, char const *) 'main.o: main.cpp :(. text + 0x2a): сначала определено здесь collect2: ld возвращено1 состояние выхода

(сначала я скомпилировал его с code :: blocks и получил ту же ошибку)

Как я могу изменить мой Modul1, чтобы не получать эту ошибку компоновки?Я не думаю, что это важно, но я использую Ubuntu 64bit с g ++ 4.4.3

Makefile:

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 ]

4 голосов
/ 01 апреля 2012

Как вы это делаете, 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!");
}

Удачи!

4 голосов
/ 01 апреля 2012

Вы включаете «easylogger-impl.h» в обе ваши единицы перевода.В easylogger-impl.h есть определения функций.Следовательно, у вас есть несколько определений ваших функций.

Одно правило определения гласит, что у вас должно быть одно и только одно определение любого объекта или функции.

Вы можете решить эту проблему, пометив все функции easylogger-impl как inline или убедившись, что они отображаются только в одной единице перевода.

...