为什么不为链接器生成重复的符号?

时间:2019-06-20 10:42:36

标签: c++ linker c++14

让我们假设以下代码:

// 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文件。没有一个。

哦,我正在使用MSVC2019。但是我对这段代码是否适用于GCC或其他编译器感兴趣。我必须进行一些测试。

1 个答案:

答案 0 :(得分:0)

阅读gudok撰写的精彩文章,如果您不熟悉的话也应该阅读,这让我现在知道发生了什么。

因此,事情是默认情况下内联了Thing :: getOne方法(因为它是在标头中定义和声明的)。内联但未扩展的方法被标记为弱链接。到此为止。