Why does C++ not have Extend feature to virtual functions?

189 views Asked by At

C++ allows defining default behavior of member functions using the virtual keyword, but what if I want to extend a member function to perform additional functionality? For example, I have the following code:

virtual void OnSize(HWND hWnd, LPARAM lParam) {
    cxClient = LOWORD(lParam);
    cyClient = HIWORD(lParam);

    rect = { 0, 0, cxClient, cyClient };
}

cxClient, cyClient, and rect are member variables that are updated on receiving a WM_SIZE message. If I want to to update the scrollbar in an inheriting class, I would have to override the function to add in this functionality but then I would need to repeat the code for updating the member variables:

void OnSize(HWND hWnd, LPARAM lParam) override {
    cxClient = LOWORD(lParam);
    cyClient = HIWORD(lParam);

    rect = { 0, 0, cxClient, cyClient };

    vScrollBar->setInfo(cyClient); // new functionality
}

Why does C++ not provide extend keyword to allow extending on the default behavior of a virtual function, that is, retaining the default behavior and incorporating additional functionalities. e.g:

void OnSize(HWND hWnd, LPARAM lParam) extend {
    vScrollBar->setInfo(cyClient); // new functionality
}

Is this considered in the upcoming revision of C++?

2

There are 2 answers

0
DevSolar On BEST ANSWER

In DerivedClass::OnSize(), you can call BaseClass::OnSize() to achieve just what you want. No special keyword needed.

struct BaseClass
{
    virtual void OnSize(HWND hWnd, LPARAM lParam) {
        cxClient = LOWORD(lParam);
        cyClient = HIWORD(lParam);

        rect = { 0, 0, cxClient, cyClient };
    }

    // ...
};

struct DerivedClass : public BaseClass
{
    void OnSize(HWND hWnd, LPARAM lParam) override {
        BaseClass::OnSize(hWnd, lParam);
        vScrollBar->setInfo(cyClient);
    }

    // ...
};

The C++ committee is hesistant to add additional keywords to the language, especially for things that have always been possible without them. There is the danger of rendering existing code, which might use macros, compiler extensions etc., invalid by such extensions of the language proper. Hence, I would be rather surprised to see extends being considered for upcoming revisions of C++. The existing construct allows derived classes to have code both before and after the call to the base class functionality, which is actually superior to extends.

4
NathanOliver On

One way around this issue is to provide two functions. One concrete function that is not virtual that has the common code to run and then another virtual function that you call at the end of the concrete function that has the class specific behavior you want to incorporate. That would look like

struct Base
{
    void do_action() { common_action; do_action_impl(); }
private:
    virtual void do_action_impl() {} // empty for the base class, you could have code here as well for the base class
};

struct Derived : Base
{
    //do_action is inherited
private:
    virtual void do_action_impl() { derived_specific_code; }
};

and now if you have a Derived object d calling do_action will call the base class function which will run the common code and then virtual dispatch to d's do_action_impl.