g++可以很好地链接带有旧代码的旧对象文件

g++ links fine with old object files with old code

本文关键字:代码 对象 文件 很好 链接 g++      更新时间:2023-10-16

base1.h

void base2::base22fun()
{
  cout<<"inside base2::base22fun()"<<endl;
}

base1.cpp

#include "base1.h"
#include "iostream"
using namespace std;
void base1::base1fun()
{
  cout<<"inside base1::base1fun()"<<endl;
}

base2.h

class base2
{
 public:

  virtual void base2fun();
};

base2.cpp

#include "base2.h"
#include "iostream"
using namespace std;
void base2::base2fun()
{
  cout<<"inside base2::base2fun()"<<endl;
}

衍生.h

#include "base1.h"
#include "base2.h"
class derived : public base1, public base2
{
 public:
  virtual void base1fun();
  virtual void base2fun();
};

导出.cpp

#include "derived.h"
#include "iostream"
using namespace std;
void derived::base1fun()
{
  cout<<"inside  derived::base1fun"<<endl;
}
void derived::base2fun()
{
  cout<<"inside  derived::base2fun"<<endl;
}

global.cpp

#include "derived.h"
static derived d;
base1& b1=d;
base2& b2=d;

main.cpp

#include "base2.h"
#include "iostream"
using namespace std;
int main()
{
  extern base2& b2;
  cout<<b2.base2fun();
 return 0;
}

我使用g++ base1.cpp base2.cpp derived.cpp global.cpp main.cpp -c 生成了所有.cpp文件的对象文件

然后我把它们都联系起来,效果很好。

现在我修改base2.h base2.cpp和main.cpp如下

base2.h

class base2
{
 public:
  int padding;
  virtual void base22fun();
  virtual void base2fun();
};

base2.cpp

#include "base2.h"
#include "iostream"
using namespace std;
void base2::base22fun()
{
  cout<<"inside base2::base22fun()"<<endl;
}
void base2::base2fun()
{
  cout<<"inside base2::base2fun()"<<endl;
}

main.cpp

#include "base2.h"
#include "iostream"
using namespace std;
int main()
{
  extern base2& b2;
  cout<<b2.padding;
 return 0;
}

然后我重新编译了base2.cpp、derived.cpp和main.cpp

我没有重新编译global.cpp,而是使用了旧的对象文件[global.o],g++链接了它们并执行了可执行文件。这怎么可能?

谢谢。

首先,学习使用makefile。这样,你就不必打那么多。。。

只要存在所需的全局符号,链接器就会成功——在这种情况下,是类的构造函数,可能还有类的vtable。您的对象在重新编译后会占用额外的空间,因此它将覆盖另一个变量。如果要添加:

static int x = 42; 

static derived d;-并且没有在构造函数中初始化padding之后,您会看到padding打印为42。

所有这些都是"未定义的行为"。它可以以任何看似合理的方式失败——格式化硬盘、发动第三次世界大战,或者"有微妙副作用的工作"。使用设置了相关依赖项的makefile,以便在base2.h发生更改时自动重新编译objects.cpp,这将是正确的做法。

对象"static-derived;"是在运行exe时创建的。它与compile和link无关。所以它起了作用。