【问题标题】:How to properly override function with different arguments in derived class?如何在派生类中正确覆盖具有不同参数的函数?
【发布时间】:2023-03-09 12:15:01
【问题描述】:

我正在为我大学的 c++ 类制作一个简单的 MVC 示例。首先,看代码: executor.h 部分:

    class IExecutor {
    IParams params;
public:
    virtual void initialize(IParams iParams);
    virtual void execute();
};

class QEExec : public IExecutor {
public:
    void initialize(QEParams iParams) override;
    void execute() override;
};

现在是 params.h 部分:

class IParams {

};

class QEParams : public IParams {
public:
    int a;
    int b;
    int c;
};

问题是我想为QEExec 创建void initialize(QEParams iParams) 函数并将QEParams 传递给它,以便访问a、b 和c 参数(稍后我需要)但我可以不要因为virtual void initialize(IParams) 而这样做。我认为如果QEParams 是从IParams 派生的,我将能够这样做,但我无法访问我之前提到的参数。如何使其工作,以便我能够在初始化函数中访问 a、b 和 c 参数? 编辑:我会放一张它应该是什么样子的照片: https://i.stack.imgur.com/KWaSQ.jpg

【问题讨论】:

  • 将参数声明为具有引用类型。
  • 你的意思是IExecutor或QEexec中的参数?因为我尝试添加引用,但它仍然会引发类型不匹配错误。
  • @VladfromMoscow 这不起作用:godbolt.org/z/2qnuB_
  • 如果我有一个IExecutor* ex = new QEExec(); 并打电话给ex->initialize(myIParams);,你期望会发生什么?你的IExecutor 界面说我可以做到!您想要明确要求“派生类必须使用从IParams 派生的东西进行初始化”的原因是什么?
  • 这不是覆盖,因为它是不同的类型。有人可以写:IExecutor *i = new QEExec; IParams p; i->initialize(p);,它会做什么?

标签: c++ class parameters derived-class


【解决方案1】:
  1. 界面没有任何字段
  2. 接口只有纯虚方法
  3. IExecutor 的名称 initialize 表示存在一些误解。看起来它应该在施工期间的乞讨时被调用一次。它应该隐藏在某些工厂创建实现IExecutor的对象的步骤中

所以基本上我怀疑你需要更多这样的东西:

class IExecutor
{
public:
    virutal ~IExecutor() {}
    virtual void execute() = 0;
};

struct QEParams {
    int a;
    int b;
    int c;
};

class QEExec: public IExecutor
{
public:
    QEExec(int b, int c) ....

    void initialie(); // second step init

    void execute() override;
};

class CAExec: public SomeOtherBaseClass, public IExecutor
{
public:
    CAExec(int a, int c) ....

    void execute() override;
};

std::unique_ptr<IExecutor> executorFactory(const QEParams& params)
{
    if (params.a < 0) {
        auto result = std::make_unique<QEExec>(params.b, params.c);
        result->initialie();
        return result;
    }
    return std::make_unique<CAExec>(params.a, params.c);
}

通常工厂参数是结构数据,额外的抽象已经过时了。

如果需要不同类型的参数来创建IExecutor 的替代版本,您只需提供不同的工厂函数(可能重载):

std::unique_ptr<IExecutor> executorFactory(const std::string& fileName)
{
    ....
}

【讨论】:

    【解决方案2】:

    听起来您使用 OOP 不正确。

    由于QEExec 是一个 IExecutor(它继承),它可以initialize 就像IExecutor 一样,理想情况下,这两个初始化都会做类似的事情IParams 对象。如果是这样,那么应该对abc 采取行动的人应该是QEParams,而不是QEExec

    您可以使用多态性来做到这一点,例如:

    class IParams {
        virtual void init_logic() { }
    };
    
    class QEParams : public IParams {
    public:
        void init_logic() { /* Do something with a/b/c */ }
    private:
        int a;
        int b;
        int c;
    };
    

    然后……

    class IExecutor {
        IParams params;
    public:
        virtual void initialize(IParams *iParams);
        virtual void execute();
    };
    
    class QEExec : public IExecutor {
    public:
        //Will call the QEParams init_logic when passed a QEParams pointer
        void initialize(IParams *iParams) { iParams->init_logic(); }
        void execute() override;
    };
    

    【讨论】:

    • 感谢您的回答。所以事实证明没有办法定义我要传递给初始化方法的对象类型?我的示例中不仅有 QEExec 和 QEParams,而且我希望初始化方法以对 QEParams 等内部的不同变量进行一些操作,最后将它们以不同的形式放入基类 IExecutor 的 params 字段中,因为我稍后会需要它们。
    • @Piston 如果您的QEExec 只能QEParams 一起工作,那么它根本不应该从IExecutor 继承。这就是我想在这里说的。我不清楚你要做什么,但很清楚,由于你设计和构建这些类的方式,你正试图与类系统作斗争。
    猜你喜欢
    • 2014-01-15
    • 1970-01-01
    • 1970-01-01
    • 2018-12-23
    • 2013-09-11
    • 1970-01-01
    • 2022-01-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多