Strange behaviour when calling virtual functions

两盒软妹~` 提交于 2019-12-09 18:33:39

问题


I don't understand what is wrong with this code. It looks like an incredible trap !

This code :

class Foo
{
  public:
      virtual double foo(double x) const = 0;
              double foo(int x) const { return (double)(x + x); }
};

class Bar : public Foo
{
    public:
        virtual double foo(double x) const { return x * x; }
};

int main()
{
    Bar* b = new Bar;
    Foo* f = b;
    std::cout << b->foo(3) << " " << f->foo(3) << std::endl;
    std::cout << b->foo(5.0) << " " << f->foo(5.0) << std::endl;
    return 0;
}

prints the following output :

9 6
25 25

I deduce that Bar::foo(double) const is called with an implicit cast when the type of the pointer is Bar*. But why such a thing is possible without any warning ?

I work with GCC 4.7.2. I compiled with g++ -Wall foobar.cpp -o foobar.exe


回答1:


This is due to name hiding.

When you declare a function called foo in Bar, you hide all declarations with the same name in Foo.

As such, when the static type of the pointer is Bar, the compiler only finds the version in Bar which takes a double, so it implicitly converts the int to satisfy this.

If you want the int version in Foo to be visible, add a using declaration:

class Bar : public Foo
{
    public:
        using Foo::foo;
//      ^^ makes the versions in Foo visible
        virtual double foo(double x) const { return x * x; }
};



回答2:


When the type is Bar*, only one version of the method is visible, the one with the double parameter.

Base methods with the same name (but different signature) are hidden.

To make them available, you can use using Foo::foo in the derived class.

Depending on your compiler, I think you might also get warnings regarding the implicit conversion, or the fact that you apparently want to call a hidden method.




回答3:


In Foo there are two overloads of foo, one that takes a double and another that takes an int.

In Bar there is one overload of foo, the one that takes a double. This overload hides all functions with the same name from the base classes. This is called name hiding.

A fix would be to employ using declaration to bring the other foo overloads from the base class in scope of Foo derived class:

class Bar : public Foo
{
    public:
        using Foo::foo; 
        virtual double foo(double x) const { return x * x; }
};


来源:https://stackoverflow.com/questions/30751499/strange-behaviour-when-calling-virtual-functions

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!