Why does a virtual function get hidden?

2019-01-09 08:48发布

I have the following classes:

class A {
public:
    virtual void f() {}
};


class B : public A{
public:
    void f(int x) {}
};

If I say

B *b = new B();
b->f();

the compiler says error C2660: 'B::f' : function does not take 0 arguments. Shouldn't the function in B overload it, since it is a virtual function? Do virtual functions get hidden like this?

EDIT: I indeed meant to inherit B from A, which shows the same behaviour.

标签: c++ virtual hide
6条回答
Evening l夕情丶
2楼-- · 2019-01-09 09:29

No, and yes, respectively. If you want the overloading behaviour, you need to say

using A::f;

in B.

查看更多
相关推荐>>
3楼-- · 2019-01-09 09:33

When the compiler has more than one way to resolve a symbol, it has to choose which one has precedence unless the code tells it otherwise. What you are expecting is the overloading to take precedence over the overriding. (over, over, over, aaaaack! Sorry, got 'over'whelmed).

This example has B inheriting a virtual method in which the subclass provides an overloaded version. Overloads are for methods in the same class using the same method name but different signatures. Since B is a subclass of A, it is overriding f(), which means it cannot also be an overload at the same time. This is why it is being hidden.

For class A, declaring method

virtual void f() {}  

as virtual means that method will be resolved using a certain set of rules that are not consistent with your declaration of b.

B *b = new B();

By creating 'b' as an instance of "B", the compiler has no need to use the virtual nature of the method of the same name in "A".

If you had declared 'b' like this

B *b = new A();  

then the call b->f(); would indeed refer to the method in A by making use of the virtual resolution.

查看更多
不美不萌又怎样
4楼-- · 2019-01-09 09:37

B does not derive from A, the correct declaration is:

class B : public A
查看更多
▲ chillily
5楼-- · 2019-01-09 09:41

Class B does not derive from A so no function F() exists. You probably meant:

class A {
public:
    virtual void f() {}
};


class B : public A {
public:
    void f(int x) {}
};

Edit: I missed the actual function hiding. See Steve Jessop answer for more thorough explanation.

查看更多
手持菜刀,她持情操
6楼-- · 2019-01-09 09:47

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.

查看更多
何必那么认真
7楼-- · 2019-01-09 09:49

It seems that it is exist rather similar question with answer in Biern Stroustrup's FAQ: http://www.stroustrup.com/bs_faq2.html#overloadderived

As he said:

"In C++, there is no overloading across scopes"

but if you want

"That's easily done using a using-declaration"

查看更多
登录 后发表回答