为什么在虚函数中转换为基类会出现分段错误?

发布于 2024-08-28 20:40:01 字数 1153 浏览 6 评论 0原文

我想使用运算符<<打印出派生类。当我打印派生类时,我想首先打印它的基类,然后打印它自己的内容。

但我遇到了一些麻烦(请参阅下面的段错误):

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

浅忆 2024-09-04 20:40:01

尝试 Base::Print(out)

Try Base::Print(out)

最后的乘客 2024-09-04 20:40:01

对于为什么的问题:

  1. ((Base)*this).Print(out); 将当前实例切片Base-类型临时。这会导致直接调用基类方法。
  2. ((const Base*)this)->Print(out); 通过指向基类的指针调用虚方法,该方法解析为子类方法,从而导致无限递归。
  3. ((Base*)this)->Print(out); - 我很确定这是未定义的行为。

To the question of why:

  1. ((Base)*this).Print(out); slices current instance to Base-typed temporary. That results in a direct call to base class method.
  2. ((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.
  3. ((Base*)this)->Print(out); - I'm pretty sure this is undefined behavior.
年少掌心 2024-09-04 20:40:01

请改用Base::Print。虚函数被派生类重写。
本质上你是在一遍又一遍地调用 print

use Base::Print instead. Virtual functions are overriden by derived class.
In essence you are calling print over and over

葮薆情 2024-09-04 20:40:01

我建议阅读 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文