在类外调用被覆盖的方法之前,如何调用虚拟方法?

How to call the virtual method before calling overriden method outside the class?

提问人:AlexusXX 提问时间:3/21/2023 最后编辑:AlexusXX 更新时间:3/21/2023 访问量:94

问:

显而易见的解决方案是:

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将在执行 .MainGUI render code

但是,如果我不想调用继承 GUI 的每个类怎么办?以及如何仅将虚拟方法打开到特定方法?GUI::render();render()

我的第一个想法是使用一个单独的方法来调用,然后调用虚拟方法:Common render code

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();
}

此代码解决了第一个问题,但不能解决第二个问题。我可以将非虚拟设为私有,然后指定为好友打开该类的所有隐藏方法和字段。render()main()

但此解决方案可能会导致调用而不是 .我的意思是程序员的错误。renderImpl()render()

那么,如何解决这个问题呢?

编辑:

很抱歉造成混淆。我无法正确表述问题标题。

我的主要问题更多地与友好类有关,而不是与虚拟方法有关。@Jarod42的评论为我指出了正确的解决方案。

C++ 友元 虚拟继承

评论

4赞 463035818_is_not_an_ai 3/21/2023
“但是,如果我不想调用 GUI::render() 怎么办?在每个继承 GUI 的类中?“为什么你认为你需要在每个派生类中调用它?我的意思是是什么阻止你不打电话?
0赞 Jarod42 3/21/2023
看来你有 2 个问题......所以一个问题一个问题。
1赞 Richard Critten 3/21/2023
这就是 C++ 中固有函数和虚函数的工作方式。您可以在派生函数中选择是否调用基类实现,以及何时(在派生函数中 - 开始、中间、结束)进行调用。其他语言强制执行各种规则,但没有灵活性。
0赞 Jarod42 3/21/2023
“以及如何仅将虚拟方法render()打开到特定方法?” 传递键成语允许有更多关于友谊的细粒度选择。
0赞 AlexusXX 3/21/2023
@463035818_is_not_a_number例如,在 GUI 中,我有一些代码可以准备渲染引擎来渲染 GUI(例如,设置着色器程序)。如果我跳过调用基本方法的行,由于渲染引擎的状态不正确,MainGUI 将不会显示。这只是一个例子。

答:

0赞 user10 3/21/2023 #1

尝试这种模板方法模式,其中您的方法包含步骤 (),您可以:render()internal_renderoverride

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();
}