调用虚函数时的奇怪行为

时间:2015-06-10 08:51:13

标签: c++ virtual

我不明白这段代码有什么问题。它看起来像一个令人难以置信的陷阱!

此代码:

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::foo(double) const时,使用隐式转换调用Bar*。但是为什么这样的事情可以在没有任何警告的情况下发生?

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

编译

3 个答案:

答案 0 :(得分:9)

这是由于名称隐藏。

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

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

如果您希望int中的Foo版本可见,请添加using声明:

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

答案 1 :(得分:2)

当类型为double时,只显示该方法的一个版本,即using Foo::foo参数的版本。

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

要使它们可用,您可以在派生类中使用InternalResourceViewResolver

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

答案 2 :(得分:1)

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; } }; 重载:

import csv
with open('vic_visitors.csv') as f:
    reader = csv.DictReader(f)
    max = 0     
    for row in reader:
        if(float(row['2004'])>max):
            max = float(row['2004'])
            maxyear = '2004'
            maxloc = row["Victoria's Regions"]
        if(float(row['2005'])>max):
            max = float(row['2005'])
            maxyear = '2005'
            maxloc = row["Victoria's Regions"]
        if(float(row['2006'])>max):
            max = float(row['2006'])
            maxyear = '2006'
            maxloc = row["Victoria's Regions"]  
        if(float(row['2007'])>max):
            max = float(row['2007'])
            maxyear = '2007'
            maxloc = row["Victoria's Regions"]          

print("The greatest visitornumber was "+ str(max) +" in " +maxloc+ " in  the year "+maxyear)