C++ 警告:虚拟函数重载“;基础::过程“;仅在类“中部分重写”;“派生”;

C++ 警告:虚拟函数重载“;基础::过程“;仅在类“中部分重写”;“派生”;,c++,overriding,virtual-functions,name-hiding,C++,Overriding,Virtual Functions,Name Hiding,我正处于警告之下。 我的部分代码是: class Base { public: virtual void process(int x) {;}; virtual void process(int a,float b) {;}; protected: int pd; float pb; }; class derived: public Base{ public: void process(int a,float b); } void derived::p

我正处于警告之下。 我的部分代码是:

class Base {
public:
    virtual void process(int x) {;};
    virtual void process(int a,float b) {;};
protected:
    int pd;
    float pb;
};

class derived: public Base{
public:
    void process(int a,float b);
}

void derived::process(int a,float b){
    pd=a;
    pb=b;
    ....
}
我得到以下警告:

 Warning: overloaded virtual function "Base::process" is only partially overridden in class "derived"
任何方式,我已经作为虚拟函数的进程,所以我期待这个警告不应该来。。。
这背后的原因是什么???

您只重写了
进程的两个重载中的一个。您缺少仅使用
int
的重载

class Base {
public:
    virtual void process(int x) {;}; // You do *not* override this in derived
    virtual void process(int a,float b) {;}; // You do override this
// ...
};
根据您的需要,您可以:

  • 只需在
    派生的
    中重写
    int
    重载即可;或

  • 使
    int
    重载非虚拟,并让它调用虚拟
    int,float
    重载


  • 两个旁注:(a)虽然大多数编译器都接受它,但a
    。(b) 受保护的成员变量通常和公共变量一样不受欢迎;您应该使用受保护的getter/setter并将变量设为私有。

    当您重写类中的虚拟方法时,未被重写的该方法的任何重载都将隐藏在该类中,并且无法使用。因此,在您的示例中,尝试在
    派生的
    对象上调用
    进程(int)
    将失败,因为被重写的
    进程(int,float)
    已将其隐藏。

    当您声明一个与
    Base
    中的方法同名的方法时,这些方法将被隐藏

    当您重写一个方法时就是这种情况

    所以

    要解决这个问题,请使用Base::process添加

    class derived: public Base {
    public:
        using Base::process;
        void process(int a, float b);
    };
    
    class derived: public Base {
    public:
        void process(x) { Base::process(x); }
        void process(int a, float b);
    };
    
    与前面的方法一样,不要使lint警告静音, 另一种解决方法是覆盖每个方法
    过程

    class derived: public Base {
    public:
        using Base::process;
        void process(int a, float b);
    };
    
    class derived: public Base {
    public:
        void process(x) { Base::process(x); }
        void process(int a, float b);
    };
    

    长话短说,在尝试解析名称时,部分重写重载函数可能会很奇怪

    另外,从设计的角度来看。这种模式通常很奇怪。我有一个功能,我已经决定,它是相同的,足以保证相同的名称:一般来说,它是一个默契,它做同样的事情。当您在子类中更改函数的行为时,如果您只在派生类中更改它的一部分,那就很奇怪了。本质上,它很容易阅读(使用~=大约相等)

    //隐式语句

    1) Base::process(int)~=Base::process(int,float)

    2) 派生::进程(int)~=派生::进程(int,float)

    //明确陈述

    3) 基本::进程(int)=派生::进程(int)

    4) 基本::进程(整数,浮点)!=派生::进程(int,float)


    本质上,由于3和4是冲突的,那么2不可能是真的。

    警告的原因是什么

    Warning: overloaded virtual function "Base::process" is only partially overridden in class "derived"
    
    你没有覆盖所有的签名,你已经覆盖了

    virtual void process(int a,float b) {;}
    
    但不是为了

    virtual void process(int x) {;}
    
    此外,当您不重写并且不使用
    using Base::process
    将函数带到作用域时,对
    派生::process(int)
    的静态调用甚至不会编译。这是因为在这种情况下,派生没有
    进程(int)
    。所以

    Derived *pd = new Derived();
    pd->process(0);
    

    不会编译

    使用
    声明添加
    ,将修复通过指向派生*的指针对隐藏函数进行静态调用并选择运算符d.process(int)进行编译和虚拟分派(通过基指针或引用调用派生函数)进行编译时无警告的问题

    class Base {
    public:
        virtual void process(int x) {qDebug() << "Base::p1 ";};
        virtual void process(int a,float b) {qDebug() << "Base::p2 ";}
    protected:
        int pd;
        float pb;
    };
    
    class derived: public Base{
    public:
        using Base::process;
    
        /* now you can override 0 functions, 1 of them, or both
        *  base version will be called for all process(s) 
        *  you haven't overloaded
        */
        void process(int x) {qDebug() << "Der::p1 ";}
        void process(int a,float b) {qDebug() << "Der::p2 ";}
    };
    

    virtualvoidbase::process(intx)隐藏在导出的
    中。您可以使用Base::process添加
    ,以解决此问题。只有在静态调用函数时,“…对于该类是隐藏的,不能使用”。您始终可以通过基指针/引用调用它。我发现在静态上下文中调用虚拟函数很奇怪,但有时它是有意义的。所以我觉得只覆盖其中一个重载是完全合理的…@leems只覆盖一个重载当然是合理的,但我无法想象你会想要这种行为。就我个人而言,我认为这是一个设计缺陷,但我可能遗漏了重载解析工作原理或其他方面的细微差别。我所知道的就是在C++中与OOP合作很快就让我向往java。我将避免在虚拟方法中使用默认参数。@ JAROD42:你说得对。既然你这么说了,我甚至还记得Scott Meyers在有效的C++中有一个完整的项目:“永远不要重新定义继承函数的默认参数值”。所以最好使用最后一个选项。@Ashwin:所以我认为这个警告是假阳性。。。顺便说一句,void进程(intx){Base::process(x);}
    应该使警告静音…我刚刚在派生类中创建了一个伪进程函数,如下面的void进程(intx){;}。。。。它解决了我的警告…@Ashwin:所以你用与
    Base
    相同的定义覆盖它,我调用
    Base
    以确保它是相同的。我认为这一意图更加明确。我建议添加评论,告诉大家这是无声的皮棉警告。
    int main(int argc, char *argv[])
    {
        derived d;
        Base& bref = d;
        bref.process(1);    // Der::p1
        bref.process(1,2);  // Der::p2 
        return 0;
    }