1
votes

I would like to enable C4263 (Visual C++) warning on our code base, however, the warning gives out some false positives. We would like to disable the warning such that only the false positives disappear. I tried to simplify the issue with some generic code:

class B {
public:
    virtual void funcA();
    virtual void funcB();
};


class D : public B
{
    virtual void funcA(int);    
    virtual void funcB(int);
};

With this code we I get following warnings: void D::funcA(int)' : member function does not override any base class virtual member function void D::funcB(int)' : member function does not override any base class virtual member function

What I am trying to achieve is to disable the warning for funcA (or funcB) and let the rest of the class be affected by it.

I tried putting

#pragma warning(push)        
#pragma warning(disable:4263)
 .
 .
 .
#pragma warning(pop)    

around funcA but that does not solve the problem. If the pragmas wrap the whole class that both of the warnings disappear.

Any ideas?

1
That is not a false positive. You're overloading with funcA(int) but not overriding funcA(). - Captain Obvlious
It is a false positive because I do want to have a method called funcA(int). This is not an error in C++ and depending on case it may make sense. What I am trying to say is: the programmer intends to override funcB() but fails to do it hence a warning must be shown. In case of funcA, the programmer actually wants to add a funcA(int) (so no intention to override funcA()) hence s/he should have the possibility to tell the compiler that "it is ok, dont show me a warning for this" - daneel
Not an answer to your question but have you considered requiring the use of the new C++11 override keyword to your coding standard? In this case, if the programmer really intended to override funcB() and had indicated as much using override they would get error C3668. - mattnewport
Just because the compiler isn't behaving exactly how you want does not mean it's a false positive or wrong. The warning is 100% correct and should be issued based on the warning level. If you want to get rid of the warning provide a definition of funcA() in your derived class and have it call into the base. The compiler will (in most cases) optimize the call via the entry in the dispatch table. - Captain Obvlious

1 Answers

9
votes

This is a strange error given the documentation for it:

https://msdn.microsoft.com/en-us/library/ay4h0tc9.aspx?f=255&MSPPError=-2147217396

'function' : member function does not override any base class virtual member function

A class function definition has the same name as a virtual function in a base class but not the same number or type of arguments. This effectively hides the virtual function in the base class.

The last sentence is the interesting one, and it suggested to me that if you unhide the base class functions, the warning will no longer appear.

And indeed this is the case. The following code does not output C4263:

class B {
public:
    virtual void funcA();
    virtual void funcB();
};

class D : public B
{
    using B::funcA;
    using B::funcB;
    virtual void funcA(int);    
    virtual void funcB(int);
};

The warning seems a little strange. If you're dispatching from the base class pointer, it doesn't matter what functions the derived class hides, as they won't be hidden when using a base class pointer. But herein lies the answer!

What's actually happening here is the compiler is guessing your intentions. Because you are introducing a new signature, it means you will be using either polymorphic or non-polymorphic dispatch using a derived pointer (not a base pointer). If you were not doing this, it would be impossible to call your overload. The compiler figures that if you are doing this, you will be hiding the un-overridden functions. And that's what the warning is about.

In an example:

struct Base
{
    virtual void DoThing(int)
    {
        std::cout << "INT  " << std::endl;
    }
};

struct Derived: public Base
{
    virtual void DoThing(char) // Add a function to handle chars
    {
        std::cout << "CHAR  " << std::endl;
    }
};

int main()
{
    Derived *derived = new Derived;
    Base *base = derived;

    base->DoThing(1);
    derived->DoThing(1);
    derived->DoThing('a');
}

This outputs:

INT CHAR CHAR

The intention may have been to add an overload to handle a different case, but instead it's hiding all the existing overloads. The warning is correct given the rules of the language. The warning isn't exact, it's trivial to determine cases where it doesn't get invoked but it should. It in-fact does the opposite of false-warnings :)

To defeat this warning, the using declaration should be used.