Warning: overloaded virtual function "Base::process" is only partially overridden in class "derived"
Asked Answered
B

5

8

I am getting below warning . part of my code is :

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;
    ....
}

I am getting below warning :

 Warning: overloaded virtual function "Base::process" is only partially overridden in class "derived"

any way i have made process as virtual function so I am expecting this warning should not come ... What is the reason behind this ??

Bivins answered 30/1, 2014 at 17:7 Comment(1)
virtual void Base::process(int x); is hidden in derived. You may add using Base::process to solve that.Eulogium
D
10

The reason for the warning

Warning: overloaded virtual function "Base::process" is only partially overridden in class "derived"

is that you haven't overridden all signatures, you have done it for

virtual void process(int a,float b) {;}

but not for

virtual void process(int x) {;}

Additionally, when you don't override and don't use using Base::process to bring functions to scope the static calls to derived::process(int) won't even compile. This is because Derived has no process(int) at that case. So

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

and

Derived d;
d.process(0);

won't compile.

Adding using declaration will fix this enabling for static call to hidden functions through pointer to Derived* and select operator d.process(int) to compile and for virtual dispatch (call to derived through base pointer or reference) to compile with no warnings.

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 ";}
};

now:

int main(int argc, char *argv[])
{
    derived d;
    Base& bref = d;
    bref.process(1);    // Der::p1
    bref.process(1,2);  // Der::p2 
    return 0;
}
Ddt answered 30/1, 2014 at 17:33 Comment(0)
S
4

When you override a virtual method in a class, any overloads of that method that are not overridden are hidden for that class and cannot be used. So in your example, attempting to call process(int) on a derived object would fail because the overridden process(int, float) has hidden it.

Scag answered 30/1, 2014 at 17:15 Comment(2)
"...are hidden for that class and cannot be used" Well, only when calling the function statically. You can always call it through a Base pointer / reference. I find it weird to call a virtual function in a static context, yet it makes sense sometimes. So I find it totally reasonable to only override one of the overloads...Earleneearley
@Earleneearley Its certainly reasonable to only override one overload, but I can't imagine a situation in you would ever want this behavior. Personally I see it as a design flaw, but I might be missing some nuance of how overload resolution works or something. All I know for sure is working with OOP in C++ quickly makes me yearn for Java.Scag
C
1

You have only overriden one of the two overloads of process. You are missing the overload taking only an 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
// ...
};

Depending on what you want, you could:

  1. Simply override the int overload too in derived; or

  2. make the int overload nonvirtual and let it call the virtual int, float overload.

Two side notes: (a) Although most compilers accept it, a ; after a function body is syntactically wrong. (b) Protected member variables are generally frowned upon nearly as much as public ones; you should use protected getters/setters and make the variables private.

Criminology answered 30/1, 2014 at 17:13 Comment(2)
I would avoid default parameter in virtual method.Eulogium
@Jarod42: You're right. Now that you say it, I even remember that Scott Meyers has a whole item about the matter in Effective C++: "Never redefine an inherited functions default parameter value". So better use the last option.Criminology
E
1

When you declare a method with same name as one in Base, those methods are hidden.

It is the case when you override one method.

So

derived d;
d.process(42); // won't compile

To solve that: add using Base::process:

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

As previous method don't silent the lint warning, an other way to solve that is to override each method process:

class derived: public Base {
public:
    void process(x) { Base::process(x); }
    void process(int a, float b);
};
Eulogium answered 30/1, 2014 at 17:21 Comment(3)
@Ashwin: So I see this warning as false positive... Btw void process(int x) { Base::process(x); } should silent the warning...Eulogium
I have just created one dummy process function in derived class like below void process(int x) {;}; ....It resolved my warning ...Bivins
@Ashwin: So you override it with same definition as Base, mine calls Base to be sure it is the same. The intend is clearer I think. I suggest to add comment to tell it is to silent lint warning anyway.Eulogium
H
0

C++ overload resolution.

Long story short, partial overriding an overloaded function can be weird when trying to resolve the name.

Also, from a design standpoint. the pattern is generally odd. I have a function that I've decided is the same enough to warrant the same name: in general, it is a tacit agreement that it does the same thing. When you change the behavior of a function in the child class, then, it is weird if it you only change part of it in derived. Essentially, its easy to read (using ~= as about equal)

//IMPLICIT STATEMENTS

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

2) derived::process(int) ~= derived::process(int,float)

//EXPLICITE STATEMENTS

3) Base::process(int) == derived::process(int)

4) Base::process(int,float) != derived::process(int,float)

essentially, since 3 and 4 are in conflict, then 2 can't possibly be true.

Hellas answered 30/1, 2014 at 17:22 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.