话说有这样的一族函数:
1
2
3
4
5
| void insert(BaseWidget* w, int i = -1);
void insert(ThinWidget* w, int i = -1);
void insert(ThickWidget* w, int i = -1);
void insert(BigWidget* w, int i = -1);
void insert(SmallWidget* w, int i = -1);
|
其中xWidget都继承自BaseWidget。这些函数大体功能都一样,只是细微上有一点差别,比如要对BigWidget重新做布局,或者设置ThickWidget的边框。
然后,有人把这些东西改成:
1
2
3
4
5
| void insert(BaseWidget* w, int i = -1);
void insert(ThinWidget* w, int i);
void insert(ThickWidget* w, int i);
void insert(BigWidget* w, int i);
void insert(SmallWidget* w, int i);
|
结果会怎么样呢?
那就是,所有忽略i值的调用都会自动转向:
1
| insert(BaseWidget* w, int i = -1)
|
编译不会出错,运行不会出错,行为…………自然就出错了………………
原因是,如果有ThinWidget *thinW,那么调用:
最初的设计会调用重载:
1
| void insert(ThinWidget* w, int i = -1)
|
但如过按照后来的设计,由于最后一个参数i没有默认值,调用也就无法匹配到正确的函数,只好退而求其次,寻找父类匹配,结果就调用到了:
1
| void insert(BaseWidget* w, int i = -1)
|
考虑到C++一般是定义声明分离,而且默认参数的定义是写在声明里,所以,你就等着一头雾水的解Bug吧。
我这两天就闷了几头雾水解这个bug,查到结果后,郁闷死了,那些声明是另一个同事改的,说是为了明确函数声明……