Search code examples
c++virtualstatic-assert

Safely removing C++ hidden virtual warning


I'm getting a compilation warning from Sun C++ 5.10 compiler about a hidden virtual method in some existing code that I'm changing. For whatever reason, the author has not implemented an override of the function for a given data type. I've recreated the situation here:

// First the data types
struct Shape {};
struct Square : public Shape {};
struct Circle : public Shape {};
struct Triangle : public Shape {};

// Now the visitor classes
struct Virtual
{   
    virtual ~Virtual() {}

    virtual void visit( Square& obj ) {}
    virtual void visit( Circle& obj ) {}
    virtual void visit( Triangle& obj ) {}
};

struct Concrete : public Virtual
{   
    void visit( Square& obj ) {}
    void visit( Circle& obj ) {}
};

int main()
{   
    Concrete myConcrete;

    return 0;
}

The Concrete class does not implement void visit( Triangle& obj ) {} and this is causing the following error message:

"pv_block.cpp", line 20: Warning: Concrete::visit hides the virtual function
Virtual::visit(Triangle&).

The code works fine but it would be nice to remove this warning message. I'd like therefore to implement the function so that the compiler is satisfied but in such a way that it cannot be used - preferably detected at compile time - since it's clearly not necessary at present.

Is there a way to implement a compile assertion to allow compilation but prevent use? I don't have access to either Boost or C++11.


Solution

  • Why would you want to prevent use? Even if you (somehow) do prevent it so that the following (A) fails to compile:

    Triangle t;
    Concrete x;
    x.visit(t);
    

    the following (B) will still work:

    Triangle t;
    Concrete x;
    static_cast<Virtual&>(x).visit(t);
    

    So IMO, it doesn't make sense to try to prevent it from being called. I would solve the warning by adding a using declaration into the Concrete class, like this:

    struct Concrete : public Virtual
    { 
        using Virtual::visit;
        void visit( Square& obj ) {}
        void visit( Circle& obj ) {}
    };
    

    This will silence the warning, and enable (A). But I don't believe it's wrong to enable (A) in this case.