繁体   English   中英

调用虚函数时的奇怪行为

[英]Strange behaviour when calling virtual functions

我不明白这段代码有什么问题。 它看起来像一个不可思议的陷阱!

这段代码:

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;
}

打印以下输出:

9 6
25 25

我推断当指针的类型为Bar*时,使用隐式转换调用Bar::foo(double) const 为什么这样的事情可能没有任何警告?

我与GCC 4.7.2合作。 我用g++ -Wall foobar.cpp -o foobar.exe

这是由于名称隐藏。

Bar声明一个名为foo的函数时,在Foo隐藏所有具有相同名称的声明。

因此,当指针的静态类型为Bar ,编译器只会Bar找到带有double的版本,因此它会隐式转换int以满足此要求。

如果您希望Fooint版本可见,请添加using声明:

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

当类型为Bar* ,只能看到该方法的一个版本,即带有double参数的版本。

隐藏具有相同名称(但不同签名)的基本方法。

要使它们可用,您可以在派生类中using Foo::foo

根据您的编译器,我认为您可能也会收到有关隐式转换的警告,或者您显然想要调用隐藏方法的事实。

Foo有两个foo重载,一个采用double ,另一个采用int

Bar有一个foo重载,一个需要double重载。 此重载会隐藏基类中具有相同名称的所有函数。 这称为名称隐藏

修复方法是使用声明来从Foo派生类范围内的基类中引入其他foo重载:

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM