首页 > 解决方案 > 为什么这不会为链接器生成重复的符号?

问题描述

让我们假设以下代码:

// IInterface.h

#pragma once

class IInterface
{
  public:
  struct Thing
  {
    // If i uncomment this line, I can see that all object files increase in size.
    // char data[10240];
    int getOne() { return 1;}
  };
  // The interface doesn't really matter
};

// Derived1.h
#pragma once
#include "IInterface.h"

class Der1: public IInterface
{
  public:
  int getOne();
};

// Derived2.h
#pragma once
#include "IInterface.h"

class Der2: public IInterface
{
  public:
  int getOne();
};

// Derived1.cpp
#include "Derived1.h"

int Derived1::getOne()
{
  Thing thing;
  return thing.getOne();
}

// Derived2.cpp
#include "Derived2.h"

int Derived2::getOne()
{
  Thing thing;
  return thing.getOne();
}

// main.cpp

// Not really needed I guess?

#include "Derived1.h"
#include "Derived2.h"

int main(int argc, char* argv[])
{
  Der1 der1;
  Der2 der2;

  return der1.getOne() - der2.getOne();
}

现在我不知道如何用语言表达这个问题,但我开始了。

为什么方法 IInterface::Thing::getOne 不会生成链接器错误,因为它在不同的翻译单元中有多个版本?

如果我制作了一个版本,其中 getOne 只是在 IInterface.h 中声明和定义的全局函数,那将产生链接器错误。

我知道我可以将结构移动到单独的 .cpp 文件,但由于它是 IInterface 并且我使用的是 C++17,因此我不需要 .cpp 文件。没有一个。

哦,我在 MSVC 2019 上。但我很感兴趣这段代码是否适用于 GCC 或其他编译器。我将不得不进行一些测试。

标签: c++linkerc++14

解决方案


阅读gudok的优秀文章,如果你不熟悉,你也应该阅读,让我现在明白发生了什么。

所以问题是 Thing::getOne 方法默认是内联的(因为它是在标题中定义和声明的)。内联但未扩展的方法被标记为弱链接。这就是结束。


推荐阅读