C++ g++;使用旧代码的旧对象文件链接良好
base1.h base2.cppC++ g++;使用旧代码的旧对象文件链接良好,c++,linker,g++,C++,Linker,G++,base1.h base2.cpp class base2 { public: virtual void base2fun(); }; class base2 { public: int padding; virtual void base22fun(); virtual void base2fun(); }; 导出的.cpp #include "base1.h" #include "base2.h" class derived : public base1, pu
class base2
{
public:
virtual void base2fun();
};
class base2
{
public:
int padding;
virtual void base22fun();
virtual void base2fun();
};
导出的.cpp
#include "base1.h"
#include "base2.h"
class derived : public base1, public base2
{
public:
virtual void base1fun();
virtual void base2fun();
};
main.cpp
#include "derived.h"
static derived d;
base1& b1=d;
base2& b2=d;
#include "base2.h"
#include "iostream"
using namespace std;
void base2::base22fun()
{
cout<<"inside base2::base22fun()"<<endl;
}
void base2::base2fun()
{
cout<<"inside base2::base2fun()"<<endl;
}
base2.cpp
class base2
{
public:
virtual void base2fun();
};
class base2
{
public:
int padding;
virtual void base22fun();
virtual void base2fun();
};
#包括“base2.h”
#包括“iostream”
使用名称空间std;
void base2::base22fun()
{
无法对象“static-derived d;”是在运行exe时创建的。它与complie和link无关。因此它起作用了。首先,学会使用生成文件。
。这样,你就不必键入太多内容了
只要存在所需的全局符号(在本例中是类的构造函数,可能还有类的vtable),链接器就会成功。重新编译后,对象会占用额外的空间,因此它会覆盖另一个变量。如果要添加:
#include "base2.h"
#include "iostream"
using namespace std;
int main()
{
extern base2& b2;
cout<<b2.padding;
return 0;
}
在构造函数中静态派生d;
-且未初始化填充
之后,您将看到填充
打印为42
所有这些都是“未定义的行为”。它被允许以任何看似合理的方式失败——格式化硬盘、发动第三次世界大战或“有微妙副作用的工作”。使用设置了相关依赖项的makefile
,以便在base2.h
发生更改时自动重新编译对象。cpp
是正确的做法。这为什么令人惊讶?为什么您认为链接器无法链接在不同时间编译的对象文件?@user657267global.o中的de>派生d
是根据base2
的旧定义,因此在修改base2
时它不应该工作。如果我有错误,请更正,但编译器分配的空间“更小”因为编译器在编译时分配大小。空间是在exe启动时分配的。不。检查生成的程序集文件(-S在gcc/clang中)-它将有类似于d:.0 8
(或4)-使用修改过的对象重新编译,以及8(或4)将更改为12或16或其他。除非您误解了我的意思,否则我很抱歉,因为还不完全清楚-对象的大小是在编译时确定的-它占用的实际内存当然是在加载可执行文件时分配的。但关键是大小是在编译时确定的,而不是在运行时确定的我,对于对象。抱歉,我误解了。即使我试图从main调用base2::base22fun
,它仍然有效。这是否有效,因为base2
只有一个vtable?谢谢!是的,应该只有一个vtable(对于给定的类)
class base2
{
public:
int padding;
virtual void base22fun();
virtual void base2fun();
};
#include "base2.h"
#include "iostream"
using namespace std;
void base2::base22fun()
{
cout<<"inside base2::base22fun()"<<endl;
}
void base2::base2fun()
{
cout<<"inside base2::base2fun()"<<endl;
}
#include "base2.h"
#include "iostream"
using namespace std;
int main()
{
extern base2& b2;
cout<<b2.padding;
return 0;
}
static int x = 42;