以下示例产生此运行时错误:
pure virtual method called
terminate called without an active exception
e.g。
template<class DERIVED>
struct Base {
int val;
Base(int i) : val(static_cast<DERIVED*>(this)->init_val(i)) {}
virtual int init_val(int i) = 0;
};
struct Derived : public Base<Derived> {
Derived(int i): Base<Derived>(i) {}
int init_val(int i) override {return i;}
};
int main(){
Derived d{100};
cout << d.val;
}
另一方面,下一个例子有效;按预期印刷100:
template<class DERIVED>
struct Base {
int foo(int i){return static_cast<DERIVED*>(this)->bar(i);}
virtual int bar(int i) = 0;
};
struct Derived : public Base<Derived> {
int bar(int i) override {return i;}
};
int main(){
Derived d;
cout << d.foo(100);
}
也许最有趣的是,如果你没有将init_val()声明为虚拟/覆盖函数,它就可以工作。有人认为这是重复的。我对可能重复的问题的理解是虚拟函数不能在基础构造函数中调用,因为孩子还没有存在。鉴于当init_val不是虚拟代码时代码有效,建议的重复问题不适用于此。
Clang和g ++使用c ++ 17生成相同的行为。
为什么在一个方法中调用它时,在base的构造函数中调用typecast-virtual-function会失败呢?
更新: immibis的建议奏效了。 即将构造函数中对虚拟库的调用更改为:
static_cast<DERIVED*>(this)->DERIVED::init_val(i)
这是&#34;安全&#34;?它为什么有效?
答案 0 :(得分:1)
这是&#34;安全&#34;?
没有。您正在调用尚不存在的对象上的成员函数。在调用基类构造函数时,派生类尚未形成。因此,您无法在其上调用成员函数。
它只是&#34;工作&#34;意外地;未定义的行为未定义。