0
#include <iostream>
using namespace std;
class Widget {
public:
    int width;
    virtual void resize() { width = 10; }
};
class SpeWidget :public Widget {
public:
    int height;
    void resize() override {
        //Widget::resize();
        Widget* th = static_cast<Widget*>(this);
        th->resize();
        height = 11;
    }
};
int main() {
    //Widget* w = new Widget;
    //w->resize();
    //std::cout << w->width << std::endl;
    SpeWidget* s = new SpeWidget;
    s->resize();
    std::cout << s->height << "," << s->width << std::endl;
    std::cin.get();
}

Derived class (SpeWidget) virtual function (resize()) wants to call that in base class (Widget). Why does the above code have segment fault. Thank you!

Bryan YU
  • 77
  • 11
  • See: [Can I call a base class's virtual function if I'm overriding it?](https://stackoverflow.com/questions/672373/can-i-call-a-base-classs-virtual-function-if-im-overriding-it). Because `resize` is `virtual`, even if you call it through a `Widget*` it will call the "correct" function from the derived class `SpeWidget`. The correct syntax for calling the method from the superclass is just `Widget::resize()`. That is, you write just `void resize() override { Widget::resize(); height = 11; }`, or maybe `void resize() override { this->Widget::resize(); height = 11; }`, if you want. – HTNW Jul 10 '20 at 01:46
  • `this->Widget::resize()` is clear to explain it, I think. – Bryan YU Jul 10 '20 at 08:52

1 Answers1

1

The commented out code is right.

Widget::resize();

Your substitute code is wrong.

Widget* th = static_cast<Widget*>(this);
th->resize();

Think about it: You are calling a virtual function through a pointer to the base class. What happens when you do that with any virtual function? It calls the most derived version. In other words, endless recursion.

Joe
  • 5,394
  • 3
  • 23
  • 54
  • That makes sense. I think another explanation is `th` is a copy of `this` after `static_cast`. And then `th->resize()` can not change the content of `this`. – Bryan YU Jul 10 '20 at 08:51
  • If that helps you think about it that's great. Just remember: calling virtual functions through a pointer always goes through the vtable which means it always calls the most-derived version. There is no way to avoid it. But calling a *named* version directly (i.e. 'Widget::resize()' ) forces a specific version (the base class version) to be called. – Joe Jul 10 '20 at 14:30