C++ 为什么在链接时出现多重定义错误?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9959563/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 13:26:23  来源:igfitidea点击:

Why do I get a multiple definition error while linking?

c++ubuntulinkergcc4.4

提问by Burkhard

I use these two files hereand here.

在这里这里使用这两个文件。

I created a class in two separate files:

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

modul1.h

模块1.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

and modul1.cpp

和 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!");
}

Now I want to use this class in another file (main.cpp):

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

#include "modul1.h"

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

When I compile it with the following Makefile, I get a "multiple definition of..." error:

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

g++ main.o modul1.o -o main modul1.o: In function 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 > const&)' main.o:main.cpp:(.text+0x0): first defined here modul1.o: In function 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): first defined here collect2: ld returned 1 exit status

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 > 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 退出状态

(At first I compiled it with code::blocks and got the same error)

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

How can I modify my Modul1 in order not to get this linking error? I don't think it is important, but I am using some Ubuntu 64bit with g++ 4.4.3

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

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

采纳答案by bendervader

The way you are building this, easylogger.h (and consequently easylogger-inl.h) gets included twice, once for modul1.h and once for main.cpp

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

Your usage of it is wrong. But you can do this to make it work:

你对它的使用是错误的。但是您可以这样做以使其工作:

In modul1.h (remove #include "easylogger.h") and make it look like this

在 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

and for modul1.cpp, include the real thing

对于 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!");
}

Good luck!

祝你好运!

回答by Rob?

You include "easylogger-impl.h" in both of your translation units. There are function definitions in easylogger-impl.h. Therefore, you have multiple definitions of your functions.

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

The one definition rule says that you must have one, and only one, definition of any object or function.

一个定义规则说你必须有一个,而且只有一个,任何对象或函数的定义。

You may solve this problem either by marking all of the easylogger-impl functions as inline, or by ensuring that they appear in only one translation unit.

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