链接程序如何处理C ++头文件中的定义?

问题描述 投票:0回答:1

我想更好地了解编译c ++时链接程序如何工作。

如果我在多个cpp文件中定义函数或全局变量,则会收到多个定义的链接器错误。这是有道理的,因为我有多个版本,并且链接器无法确定特定的版本。为了避免这种情况,只能写/包括声明(仅函数签名,变量外部签名)。但是,我注意到您可以在类声明中定义方法,并且至少在这里大多数人认为对于琐碎的函数(例如琐碎的getter和setter)可以接受甚至是很好的做法,因为它允许编译器内联这些函数(并且,这对于模板是必要的。)>

在有关“一次编译指示”的讨论中,我知道在某些情况下,工具链将无法区分文件是否相同,因此,原则上,两个cpp文件可能会获得同一类从不同的标头声明的名称,但是对此类仅标头方法定义不同,不是吗?

我试图建立一个例子:main.cpp

#include <iostream>
#include "Class1.hpp"
#include "Class2.hpp"

using namespace std;

int main() {
  Class1 c1;
  Class2 c2(c1);

  c1.set(1);
  cout << c1.get() << endl;
  c2.print();

  return 0;
}

Class1.cpp:

#pragma once
#ifndef CLASS1_HPP
#define CLASS1_HPP
#warning Class1

class Class1 {
  public:
  void set(int i) { val = i; };
  int get() {return val;};

  int val=0;
};

#endif

Class1a.hpp

#pragma once
#ifndef CLASS1_HPP
#define CLASS1_HPP
#warning Class1a

class Class1 {
  public:
  void set(int i) { val = i; };
  int get() {return -1*val;};

  int val=0;
};

#endif

Class2.hpp:

#pragma once
#ifndef CLASS2_HPP
#define CLASS2_HPP

#include <iostream>
#include "Class1a.hpp"

using namespace std;

class Class2 {
  public:
  Class2(Class1 &c1) : c1(c1) {};
  void print();

  Class1& c1;
};

#endif

Class2.cpp

#include "Class2.hpp"

void Class2::print() {
  cout << c1.get() << endl;
}

但是,我得到以下输出:

$ g++ *.cpp; ./a.out     
In file included from Class2.hpp:6:0,
                 from Class2.cpp:1:
Class1a.hpp:4:2: warning: #warning Class1a [-Wcpp]
 #warning Class1a
  ^~~~~~~
-1
-1

我不太清楚为什么预编译器从来没有看到Class1(not-a),尽管它实际上是在main.cpp中首先包含的,所以我想我的问题扩展到了那个……

我想更好地了解编译c ++时链接程序如何工作。如果我在多个cpp文件中定义一个函数或一个全局变量,则会收到多个定义的链接器错误。这使得...

c++ linker toolchain
1个回答
0
投票

链接器根本不处理头文件。编译器(在预处理阶段)以文本形式将标头的内容插入源文件。然后编译生成的翻译单元。

© www.soinside.com 2019 - 2024. All rights reserved.