为什么在虚函数中转换为基类会出现分段错误?
我想使用运算符<<
打印出派生类。当我打印派生类时,我想首先打印它的基类,然后打印它自己的内容。
但我遇到了一些麻烦(请参阅下面的段错误):
class Base {
public:
friend std::ostream& operator<<(std::ostream&, const Base&);
virtual void Print(std::ostream& out) const {
out << "BASE!";
}
};
std::ostream& operator<<(std::ostream& out, const Base& b) {
b.Print(out);
return out;
}
class Derived : public Base {
public:
virtual void Print(std::ostream& out) const {
out << "My base: ";
//((const Base*)this)->Print(out); // infinite, calls this fct recursively
//((Base*)this)->Print(out); // segfault (from infinite loop?)
((Base)*this).Print(out); // OK
out << " ... and myself.";
}
};
int main(int argc, char** argv){
Derived d;
std::cout << d;
return 0;
}
为什么我不能以其中一种方式进行转换?
((const Base*)this)->Print(out); // infinite, calls this fct recursively
((Base*)this)->Print(out); // segfault (from infinite loop?)
I want to print out a derived class using the operator<<
. When I print the derived class, I want to first print its base and then its own content.
But I ran into some trouble (see segfault below):
class Base {
public:
friend std::ostream& operator<<(std::ostream&, const Base&);
virtual void Print(std::ostream& out) const {
out << "BASE!";
}
};
std::ostream& operator<<(std::ostream& out, const Base& b) {
b.Print(out);
return out;
}
class Derived : public Base {
public:
virtual void Print(std::ostream& out) const {
out << "My base: ";
//((const Base*)this)->Print(out); // infinite, calls this fct recursively
//((Base*)this)->Print(out); // segfault (from infinite loop?)
((Base)*this).Print(out); // OK
out << " ... and myself.";
}
};
int main(int argc, char** argv){
Derived d;
std::cout << d;
return 0;
}
Why can't I cast in one of these ways?
((const Base*)this)->Print(out); // infinite, calls this fct recursively
((Base*)this)->Print(out); // segfault (from infinite loop?)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
尝试 Base::Print(out)
Try Base::Print(out)
对于为什么的问题:
((Base)*this).Print(out);
将当前实例切片到Base-类型临时。这会导致直接调用基类方法。
((const Base*)this)->Print(out);
通过指向基类的指针调用虚方法,该方法解析为子类方法,从而导致无限递归。((Base*)this)->Print(out);
- 我很确定这是未定义的行为。To the question of why:
((Base)*this).Print(out);
slices current instance toBase
-typed temporary. That results in a direct call to base class method.((const Base*)this)->Print(out);
calls virtual method through a pointer to base, which resolves to the child class method, which results in infinite recursion.((Base*)this)->Print(out);
- I'm pretty sure this is undefined behavior.请改用
Base::Print
。虚函数被派生类重写。本质上你是在一遍又一遍地调用 print
use
Base::Print
instead. Virtual functions are overriden by derived class.In essence you are calling print over and over
我建议阅读 C++ Primer 第 5 卷第 607 页“规避虚拟机制”,这是一个简短的部分,讨论您所犯的那种无限递归错误。
I suggest reading C++ Primer 5th page 607 "Circumventing the Virtual Mechanism" which is a short section talking about the kind of infinite-recursion error you made.