程序如何传递链接器

How did the program pass the linker?

本文关键字:链接 何传递 程序      更新时间:2023-10-16

程序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

原因解释:

当创建派生类的对象时,程序执行以下操作:

  1. 为派生
  2. 分配足够大的内存
  3. 设置对象的虚表指针指向基类的虚表
  4. 执行Base::Base()[调用log()将调用Base::log()]
  5. 设置对象的虚表指针指向派生类的虚表
  6. 执行Derived::Derived()[调用log()将调用Derived:: log()]
  7. 对象现在已经完全构建。

您的log函数是虚拟的,因此链接器不担心它。链接器不关心虚函数,因为它们的地址只有在运行时才知道。

你的代码的问题是你从Base构造函数调用虚函数。但是在Base构造函数被调用的时候,Derived还没有被构造,所以log函数是没有定义的。

Derived类的每个对象都包含Base类的"子对象",该子对象在对象本身之前构造(即Base构造函数在Derived之前被调用)。当Base构造函数执行时,它不知道Derived类的虚表,所以它不能解析log调用的地址。因此,它认为它是一个纯虚函数并中止执行。