我不明白这段代码有什么问题。它看起来像一个令人难以置信的陷阱!
此代码:
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
答案 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)