0

The obvious solution is:

class GUI{
public:
    virtual void render() {
        //Common render code
    }
}

class MainGUI : public GUI {
private:
    void render() override {
        GUI::render();
        //MainGUI render code
    }
}

int main(...){
   GUI* mainGUI = new MainGUI();
   mainGUI->render();
}

Common render code will be executed before executing the MainGUI render code.

But what if I don't want to call GUI::render(); in every class that inherits GUI? And how to open the virtual method render() only to the specific method?

My first thought was to use a separate method to call Common render code and then call the virtual method:

class GUI{
public:
    void render(){
        //Common render code
        renderImpl();
    }
private:
    virtual void renderImpl() = 0;
}

class MainGUI : public GUI {
private:
    void renderImpl() override {
        //MainGUI render code
    }
}

int main(...){
   GUI* mainGUI = new MainGUI();
   mainGUI->render();
}

This code solves the first question, but not the second. I can make the non-virtual render() private, and then specify main() as a friend to open all the hidden methods and fields of the class.

But this solution could potentially lead to calling renderImpl() instead of render(). I mean the programmer's mistake.

So, how to solve this problem?

EDIT:

Sorry for confusion. I couldn't formulate the question title correctly.

My main problem was related more to friendly classes than to virtual methods. @Jarod42's comment pointed me to right solution.

AlexusXX
  • 15
  • 4
  • 4
    "But what if I don't want to call GUI::render(); in every class that inherits GUI?" why do you think you need to call it in every derived class? I mean what prevents you from not calling it? – 463035818_is_not_an_ai Mar 21 '23 at 14:02
  • It seems you have 2 questions... And so one question by question. – Jarod42 Mar 21 '23 at 14:07
  • 1
    This is the way inherence and virtual functions work in C++. You get the choice in the derived function whether or not to call the base class implementation and when (in the derived function- beginning, middle, end) you make the call. Other languages enforce various rules, but don't have the flexibility. – Richard Critten Mar 21 '23 at 14:07
  • *"And how to open the virtual method render() only to the specific method?"* [Pass key idiom](https://arne-mertz.de/2016/10/passkey-idiom/) allows to have more fined-grain options about friendship. – Jarod42 Mar 21 '23 at 14:10
  • @463035818_is_not_a_number for example, in the GUI I have some code that prepares rendering engine to render the GUI (set Shader Program, for example). If I skip the line with calling the base method, MainGUI will not be displayed due to the incorrect state of the rendering engine. This is just an example. – AlexusXX Mar 21 '23 at 14:15
  • This *may* be a case for the [non-virtual interface idiom](https://stackoverflow.com/questions/6481260/non-virtual-interface-design-pattern-in-c-c). – Nathan Pierson Mar 21 '23 at 14:19

1 Answers1

0

Try this sort of Template method pattern where your render() method contains step (internal_render) you can override:

class GUI {
private:
    virtual void internal_render() = 0;
    void common_render() {
        std::cout << "Common render ";
    };
public:
    void render() {
        common_render();
        internal_render();
    }
};

class MainGUI : public GUI {

private:
    void internal_render() override {
        std::cout << "Derived render";
    }
};

int main() {
    GUI* mainGUI = new MainGUI();
    mainGUI->render();
}
user10
  • 266
  • 5