-5

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++?

12
  • 4
    but then I would need to repeat the code for updating the member variables: -- Your code could simply had been: { Base::OnSize(hWnd, lParam); vScrollBar->setInfo(cyClient); }, assuming Base is the base class. Commented Mar 6, 2024 at 13:35
  • 1
    Why does C++ not provide extend keyword to allow extending on the default behavior -- All other languages that I know does this similar to C++. You need to call the base class version explicitly (Java, C#, etc.) -- there is no "extend" keyword in those other languages that calls base functions automatically. Commented Mar 6, 2024 at 13:45
  • 2
    "that is, retaining the default behavior and incorporating additional functionalities" -- should the additional functionalities occur before or after the default behavior? Providing a way to invoke the base class version of a function is more flexible than your proposed extend. Commented Mar 6, 2024 at 13:47
  • 1
    To @JaMiT's point, what if you want to perform the extra functionality before you call the base class version? How will an "extend" keyword work in that case? Commented Mar 6, 2024 at 13:48
  • 2
    @machine_1 Skipping over the basic parts of a language manual -- e.g. how a for works -- without missing the points where even those basic parts might be different from other languages, is an aquired skill. And it needs to be aquired, because one day you will be asked to work in an unfamilliar language, with very little time to prepare, and little leeway for trial & error. Commented Mar 6, 2024 at 15:35

2 Answers 2

6

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.

Sign up to request clarification or add additional context in comments.

Comments

6

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.

4 Comments

With the limit that it applies just to one level... if a class inherit from Derived, we have to add another extra method (using final might be appropriate in such case...).
@Jarod42 Does it only apply to one level? Works just fine here doing a second level: coliru.stacked-crooked.com/a/71c45c05778d4c01
D2 doesn't print "D1"... Might depend of the definition of OP for extend in such cases though (Another reasons why "extend" seems bad ;-) )...
@Jarod42 Aha, that's what you mean. Yeah, this is only ever intended to run the base and the final derived objects code.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.