Wayee
Wayee

Reputation: 459

"hides overloaded virtual functions" warning when deriving from multiple templated base classes

Suppose the code below:

Base.h

template <class T>
class Base
{
public:
    virtual void func(T value) {}
};

Derived.h

class Derived : public Base<Type1>
              , public Base<Type2>
{
public:
    void func(Type1 object) override {}
};

Basically I have a templated class with a member function that takes the argument of the template type. The derived class derive from the base with two different class type, and override the function of one of them.

With the Clang compiler, it would generate a hides overloaded virtual functions warning, which is actually intended here, i.e. I do not need Base2::func(float) in the derived class.

I am aware that by appending -Wno-overloaded-virtual to the compiler flags would mute this warning but I'm not sure that's the safe thing to do, as in other cases this warning may be valid.

In my project I have thousands of this case (i.e. many derived classes with different class types). Are there any good suggestion over it so the warning wouldn't be present for this situation but keep it for others?

Upvotes: 2

Views: 7771

Answers (2)

Peter
Peter

Reputation: 36617

I actually wouldn't use multiple inheritance in this case, since it is still possible to call Base2::func() with the help of a type conversion (e.g. convert Derived * implicitly or explicitly to a Base2 *), despite it being hidden and not in scope of Derived.

Instead, I would do

class Derived : public Base1
{
   private:
        Base2 base2;

   public:
      void func(int) override {};
};

which will mean that func(float) is not within the scope of Derived at all. Only member functions of Derived (or friends) would be able to call base2.func(some_float).

This does prevent implicit conversion of a Derived * to a Base2 * (or Derived & to a Base2 &). I'd argue that if you need such implicit conversions, then your design is broken, since that would also permit (indirectly) calling Base2::func() for an instance of Derived. Which, presumably if you want it hidden, you wish to avoid ...... Generally speaking, if you find yourself in a contradictory discussion in design (you want X, but achieving X has an unwanted effect Y) that's a sign of a design flaw.

Upvotes: 0

Jarod42
Jarod42

Reputation: 217970

The safe way is to unhide the method is with using:

class Derived : public Base1, public Base2
{
public:
    using Base2::func;
    void func(int) override {}
};

With that following works as expected:

Derived d;
d.func(4.2f); // call correctly Base2::func(float) and not Derived::func(int).

To silent the warning for intentional hiding, there are still the compiler specific way:

class Derived : public Base1, public Base2
{
public:

#pragma clang diagnostic push
# pragma clang diagnostic ignored "-Woverloaded-virtual"
    void func(int) override {}
#pragma clang diagnostic pop
};

And then:

Derived d;
d.func(4.2f); // call Derived::func(int).

Upvotes: 3

Related Questions