g++ 与旧代码的旧目标文件链接良好
g++ links fine with old object files with old code
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;
}
derived.h
#include "base1.h"
#include "base2.h"
class derived : public base1, public base2
{
public:
virtual void base1fun();
virtual void base2fun();
};
derived.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.hbase2.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++ 链接了它们并执行了可执行文件。这怎么可能?
谢谢。
对象 "static derived d;" 是在您 运行 您的 exe 时创建的。它与 complie 和 link 无关。所以它起作用了。
首先,学会使用makefile
。这样,您就不必输入那么多...
只要存在所需的全局符号,链接器就会成功 - 在这种情况下,class 的构造函数和 class 的 vtable 可能存在。您的对象在重新编译后占用了额外的 space,因此它将覆盖另一个变量。如果您要添加:
static int x = 42;
在 static derived d;
之后 - 并且不在构造函数中初始化 padding
,您会看到 padding
打印为 42。
而这一切都是"undefined behaviour"。它允许以任何看似合理的方式失败 - 格式化您的硬盘,启动世界 war III,或 "kind of work with subtle side-effects"。使用具有相关依赖项集的 makefile
以便在 base2.h
更改时自动重新编译 objects.cpp
是正确的做法。
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;
}
derived.h
#include "base1.h"
#include "base2.h"
class derived : public base1, public base2
{
public:
virtual void base1fun();
virtual void base2fun();
};
derived.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
然后我将它们全部链接起来,效果很好。
现在我修改base2.hbase2.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++ 链接了它们并执行了可执行文件。这怎么可能?
谢谢。
对象 "static derived d;" 是在您 运行 您的 exe 时创建的。它与 complie 和 link 无关。所以它起作用了。
首先,学会使用makefile
。这样,您就不必输入那么多...
只要存在所需的全局符号,链接器就会成功 - 在这种情况下,class 的构造函数和 class 的 vtable 可能存在。您的对象在重新编译后占用了额外的 space,因此它将覆盖另一个变量。如果您要添加:
static int x = 42;
在 static derived d;
之后 - 并且不在构造函数中初始化 padding
,您会看到 padding
打印为 42。
而这一切都是"undefined behaviour"。它允许以任何看似合理的方式失败 - 格式化您的硬盘,启动世界 war III,或 "kind of work with subtle side-effects"。使用具有相关依赖项集的 makefile
以便在 base2.h
更改时自动重新编译 objects.cpp
是正确的做法。