程序如何传递链接器
How did the program pass the linker?
程序link_function.cpp
#include <iostream>
class Base {
public:
Base() {
init(); // first condition
// log(); // second condition
}
virtual ~Base() {}
virtual void log() = 0;
private:
void init() {
log();
}
};
class Derived: public Base {
virtual void log() {}
};
int main() {
Derived d;
return 0;
}
第一个条件
make link_function
通过。./link_function
产生如下错误
pure virtual method called
terminate called without an active exception
Aborted (core dumped)
init()
函数如何通过链接器而不产生undefined to reference log()
错误??
第二个条件
当我注释int()
并只是调用log()时,它产生了一个linker error
。
undefined reference to 'Base::log()'
.
它们之间的有什么区别?
派生类是从基类向上构建的。在Base的构造函数期间,派生的构造函数尚未执行。因此,虚函数表还没有完成。
在构造函数中调用虚函数(即使是非纯函数)是不合适的。它暗示了一个不正确的类设计。
这是一个坏主意的原因:
#include <iostream>
using namespace std;
class Base {
public:
Base() {
init();
// log();
}
virtual void log() { cout << "stange outcome 1" << endl; }
private:
void init() {
log();
}
};
class Derived: public Base {
public:
virtual void log() { cout << "stange outcome 2" << endl;}
Derived()
: Base()
{
log();
}
};
int main() {
Derived d;
d.log();
return 0;
}
输出:Compiling the source code....
$g++ -std=c++11 main.cpp -o demo -lm -pthread -lgmpxx -lgmp -lreadline 2>&1
Executing the program....
$demo
stange outcome 1
stange outcome 2
stange outcome 2
原因解释:
当创建派生类的对象时,程序执行以下操作:
- 为派生 分配足够大的内存
- 设置对象的虚表指针指向基类的虚表
- 执行Base::Base()[调用log()将调用Base::log()]
- 设置对象的虚表指针指向派生类的虚表
- 执行Derived::Derived()[调用log()将调用Derived:: log()]
- 对象现在已经完全构建。
您的log
函数是虚拟的,因此链接器不担心它。链接器不关心虚函数,因为它们的地址只有在运行时才知道。
你的代码的问题是你从Base
构造函数调用虚函数。但是在Base
构造函数被调用的时候,Derived
还没有被构造,所以log
函数是没有定义的。
Derived
类的每个对象都包含Base
类的"子对象",该子对象在对象本身之前构造(即Base
构造函数在Derived
之前被调用)。当Base
构造函数执行时,它不知道Derived
类的虚表,所以它不能解析log
调用的地址。因此,它认为它是一个纯虚函数并中止执行。
相关文章:
- 将函数传递给动态链接库
- LLVM 传递链接问题:未定义的符号
- LLVM 通行证:破坏库未与传递库链接
- 传递"-l"<libname>还是将"<libname>lib.a"直接传递给链接器?
- 基于CMAKE的CUDA应用程序的构建失败 - 没有传递给链接器的文件
- 如何使用通过引用传递的值进行更新以删除双链接列表中的出现次数
- 链接模板与传递 stl 容器的问题
- 如何通过Gradle将链接标志传递到Android Studio中的CMAKE
- 与链接列表运算符中的传递值(例如C 标头文件中的删除(front))中,我如何使用布尔函数
- 为什么我必须在链接器行的末尾传递库
- 针对库链接但直接传递obj文件的未解析名称可以正常工作
- 将静态常量int作为引用传递时发生链接器错误
- 链接错误:无法弄清楚如何将数组作为函数参数传递/接收
- 将命令行实用程序的输出传递给编译器/链接器
- Eclipse-CDT/ c++:未定义的引用-错误,尽管正确的.o文件被创建并传递给链接器
- 作为绝对路径传递给链接器的动态库被相对路径加载
- 将此从构造函数传递给其他构造函数会在链接时产生未定义的引用
- 使用 CMake 交叉编译:如何排除默认 qt 库,而不是将它们传递给链接器的命令行
- 程序如何传递链接器
- 条件传递链接库