这是程序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()'
。
他们之间的差异是什么?
答案 0 :(得分:2)
派生类是从基类构建的。在Base的构造函数期间,Derived的构造函数尚未执行。因此,vtable尚未完成。
在构造函数中调用虚函数(甚至是非纯函数)是顽皮的。这意味着不正确的课程设计。
这就是为什么这是一个坏主意:
#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
解释原因:
当我们创建Derived类的对象时,程序执行以下操作:
答案 1 :(得分:0)
您的log
功能是虚拟的,因此链接器并不担心。 Linker并不关心虚函数,因为它们的地址仅在运行时才知道。
您的代码的问题是您从Base
构造函数调用虚函数。但是在调用Base
构造函数时,Derived
尚未构造,因此log
函数尚未定义。
Derived
类的每个对象包含&#34;子对象&#34;在对象本身之前构造的Base
类(即Base
构造函数在Derived
之前调用)。当Base
构造函数执行时,它不知道Derived
类的虚拟表,因此它无法解析log
要调用的地址。因此,它认为它是纯虚函数并中止执行。