从链接器重现“多个声明”错误

Reproducing "multiple declarations" error from linker

提问人:jgreen81 提问时间:4/13/2023 更新时间:4/13/2023 访问量:33

问:

因此,我将向一所大学演示 C++ .h 文件中的(非模板)实现问题。

但现在我无法按预期重现它。这是我的代码:

// common.h

#ifndef common_h
#define common_h

#include <iostream>

class common
{
    public:
    void Hello() {
        // Implementation in header file
        std::cout << "Hello from common" << std::endl;
    }
};

#endif // common_h
// user1.h

#ifndef user1_h
#define user1_h

#include "common.h"

class user1
{
    public:
    user1();
    
    private:
    common g;
};

#endif // user1_h
// user1.cpp

#include "user1.h"

#include <iostream>

user1::user1()
{
    std::cout << "Constructing user 1" << std::endl;
    g.Hello();
}
// user2.h

// Exactly as user1.h except the class+constructor name
// user2.cpp

// Exactly as user1.cpp except the class+constructor name
// main.cpp

#include "user1.h"
#include "user2.h"

int main()
{
    user1 u1;
    user2 u2;
}

我正在编译这样的代码:

g++ -c -g -O0 -fno-lto -fno-inline-small-functions user1.cpp
g++ -c -g -O0 -fno-lto -fno-inline-small-functions user2.cpp
g++ -c -g -O0 -fno-lto -fno-inline-small-functions main.cpp

g++ user1.o user2.o main.o

没有任何失败,程序按预期工作。

为什么我在 common.h 的“Hello”函数上没有收到“多个声明”错误?

我查看了对象文件(使用 objdump),我看到了这个标签:LINK_ONCE_DISCARD。难道这就是原因吗?谁能提供更多细节?我敢肯定我以前见过这种情况,所以一定有什么变化(可能是来自编译器更新或其他什么)。

编译器版本:

>g++ --version
g++ (Rev2, Built by MSYS2 project) 12.1.0
Copyright (C) 2022 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
C G++ 链接器错误 多定义错误

评论

3赞 BoP 4/13/2023
在类声明中定义的函数是自动的,因此链接器负责删除重复项。inline
0赞 jgreen81 4/13/2023
哇。我不知道。在外部定义 Hello(但仍在头文件中)给了我预期的错误。谢谢你,@BoP
0赞 jgreen81 4/13/2023
@DoP,你真的是指“内联”,即代码将内联在调用者中,而不是导致对“Hello”的调用吗?
0赞 wohlstad 4/13/2023
@jgreen81 是的,尽管您应该记住内联只是对编译器的“建议”(即无论如何都可以忽略它)。
0赞 BoP 4/13/2023
inline 关键字有两个含义 - 一个函数可以内联扩展,并且可以多次包含而不创建重复项。第二部分是当今最重要的部分。现代编译器倾向于在有意义的地方扩展函数,无论它们是否被标记 - 这就是为什么你需要要求它不要......-fno-inline-small-functions

答:

0赞 jgreen81 4/13/2023 #1

感谢@BoP,答案如下:

https://en.cppreference.com/w/cpp/language/inline

我的“Hello”函数是内联的,因为它是在类声明中定义的。