Why Does a Virtual Function Get Hidden

Why does a virtual function get hidden?

Assuming you intended B to derive from A:

f(int) and f() are different signatures, hence different functions.

You can override a virtual function with a function that has a compatible signature, which means either an identical signature, or one in which the return type is "more specific" (this is covariance).

Otherwise, your derived class function hides the virtual function, just like any other case where a derived class declares functions with the same name as base class functions. You can put using A::f; in class B to unhide the name

Alternatively you can call it as (static_cast<A*>(b))->f();, or as b->A::f();. The difference is that if B actually does override f(), then the former calls the override, whereas the latter calls the function in A regardless.

C++ Virtual function being hidden

The issue that you are experiencing is related to how name lookup works in C++. In particular, when resolving a member, the compiler will look into the static type of the object on which the member is being accessed. If the identifier is found in that class, then lookup completes and (in the case of member functions) overload resolution starts. If the identifier is not found, it will crawl up the hierarchy, class by class, trying to locate the identifier one level at a time.

In your particular case, you have c->onFoo(); and c is of type C. The compiler does not see any declaration of onFoo in C, so it continues upwards in the hierarchy. When the compiler checks B, it sees that there is a declaration of void onFoo(int i) at that level, so it stops lookup, and tries overload resolution. At this time, the overload resolution fails due to the inconsistency in the arguments.

The fact that a declaration of void onFoo(int) is present at B level has the effect of hiding the rest of the overloads in any base class, as it will stop lookup. Note that this is a problem with unqualified lookup, the function is still there and applicable to the object, but will not be found by regular lookup (you can still call it as c->A::onFoo()).

As of how to deal with hiding, the simplest way is by employing the using declaration to bring the functions into scope:

class B : A {
public:
using A::onFoo; // All A::onFoo overloads are *considered* here
void onFoo( int );
};

The effect of the using declaration here is that when the B class is looked up, in search for the onFoo identifier, the compiler is instructed to also consider all overloads of onFoo in the base class, enabling regular lookup to find A::onFoo().

Is it valid to hide a base class virtual function by making it pure virtual in derived classes?

It is clearly allowed and supported by the standard (cf, for example, this online C++ standard draft), and thus clearly not undefined behaviour:

10.4 Abstract classes

5 [ Note: An abstract class can be derived from a class that is not
abstract, and a pure virtual function may override a virtual function
which is not pure. — end note ]

The effect is that your class B becomes abstract and any subclass - if it shall not be abstract, too - must define f() then; the implementation in class A can still be invoked through A::f(), such that it is - from the perspective of reusing the implementation - not pointless.

Hiding a private overloaded virtual function?

After all, DB cannot even see the hidden function (which might even be named the same by coincidence).

Accessibility and visibility are different concepts in C++. DA::f() is by default visible inside DB (and then hidden by DB::f()), but it is not accessible, because it is private inside DA, and DB is not a friend of DA. One could argue that hiding a function that is inaccessible is harmless, because it cannot be called anyway. However, the distinction between hidden and inaccessible can be significant because visible and inaccessible functions do participate in overload resolution. If db is an object of type DB, then what does db.f(0) do? If DA::f() is visible but inaccessible, it will be selected as best match and the compiler will emit a diagnostic because it is inaccessible and therefore cannot be called. If DA::f() is hidden, however, the compiler will select the overload that accepts a pointer instead, and treat the literal 0 as a null pointer.

Can you Hide a virtual method in c++?

Why anyone would do something like that? It breaks base class contract.
If you don't want to implement subclass that has the same interface as base class, why do you inherit at all?
Use composition.

There is no equivalent of C# new keyword in C++.
So you cannot cancel method's 'virtualness'.

If you really want to do this you can always:

  • override a method in subclass as private.

  • create overload. But the overload has to have different parameters.

But if you do this, IMHO something is wrong with your design.
I wish each C++ compiler caught both of this situations at least as warnings.

hidden overloaded virtual function with more than 2 classes

The declaration of void visit(B&) or any declaration a member named visit (it could have been a data member int visit;) in visitor3 hides any member of a parent called visit.

Here the warning of the compiler is more a goodies. It recognized a common mistake pattern which consists in overriding a base virtual member function without taking care over of overloads. But it does not detect all hidden names, or does not warn for all of them. Whatsoever, all visit from visitor1 and visitor2 are hidden.

Additional answer: The using declaration that name members of a base class is a declaration inside the derived class of all the members in the base class that have that name and are visible. So this effectively include members that where also declared by a using declaration in the base class.

(These members declared by a using declaration behave closely as if they were actual members first declared in that class. Even overload resolution considers their implied object parameter to be of the type of the derived class.)

xcode - why is a warning of 'is hidden' given with overloaded virtual functions

I guess one of the classes derived from A (let's say it's B) only overrides one of the overloads of methodA(). In this case, the other overload of methodA is hidden in B. Example:

class A {
public:
virtual void methodA(int) {}
virtual void methodA(int, int, int) {}
};

class B : public A {
public:
virtual void methodA(int) {}
};

int main()
{
A a;
B b;
A *pa = &b;
a.methodA(7); //OK
a.methodA(7, 7, 7); //OK
pa->methodA(7); //OK, calls B's implementation
pa->methodA(7, 7, 7); //OK, calls A's implementation
b.methodA(7); //OK
b.methodA(7, 7, 7); //compile error - B's methodA only accepts one int, not three.
}

The solution is to add a using declaration into B:

class B : public A {
public:
using A::methodA; //bring all overloads of methodA into B's scope
virtual void methodA(int) {}
};


Related Topics



Leave a reply



Submit