- 例一:
#include <stdio.h>
void f(int a);
void f(long a);
void f(char a);
int main(int argc,char *argv[])
{
double value = 65.01;
f(value);
return 0;
}
void f(int a)
{
printf("int value=%d/n", a);
}
void f(long a)
{
printf("long value=%d/n", a);
}
void f(char a)
{
printf("char value=%c/n", a);
}
编译上面的代码,出现如下错误:
error C2668: “f” : 对重载函数的调用不明确
在 f(value);调用中,由于存在隐式数据转换为,value自动转换成整形值65,但是char,int,long都属于整型,编译器不知道该调用f(char),f(int),还是f(long),由于程序运行路径具有可预知的唯一路径,编译器不能帮程序设计者决定使用那个函数,所以不能通过编译。 - 例二:
#include <stdio.h>
void f(int a);
void f(long a);
void f(char a);
int main(int argc,char *argv[])
{
double value = 65.01;
f(static_cast<int>(value));
f(static_cast<char>(value));
f(static_cast<long>(value));
return 0;
}
void f(int a)
{
printf("int value=%d/n", a);
}
void f(long a)
{
printf("long value=%d/n", a);
}
void f(char a)
{
printf("char value=%c/n", a);
}
上面的程序由于使用了static_cast进行了明确的类型转换,编译器知道程序将调用哪一个函数,所以能正确运行。 - 总结
如果在程序中涉及到函数重载,相同位置上的参数如果是char,short,int,long,unsigned short,unsigned int,unsigned long,unsigned char,那么可能会引起二义性,应该多加注意,在调用函数的地方一定要进行显示的类型转换。 - 例三
#include <stdio.h>
class Base
{
public:
void f(int a){printf("Base f:para=%d/n", a);}
};
class Derived: public Base
{
public:
void f(long a){printf("Derived f:para=%d/n", a);}
};
int main(int argc,char *argv[])
{
Derived d;
Base &b = d;
d.f(1);
b.f(1);
return 0;
}
这个程序可以成功通过编译,并运行吗?答案是肯定的,因为Derived中f函数是重新定义,不是重载,由于函数f不是虚函数,那么调用f函数的时候,将来根据对象的静态类型来调用对应类的函数.
d.f(1);由于d的静态类型是Derived ,所以将调用Derived::f(long a)函数;
b.f(1);由于B的静态类型是Base,所以将调用Base::f(int a)函数;
运行结果:
Derived f:para=1
Base f:para=1 - 例四
#include <stdio.h>
class Base
{
public:
virtual void f(int a){printf("Base f:para=%d/n", a);}
};
class Derived: public Base
{
public:
virtual void f(long a){printf("Derived f:para=%d/n", a);}
};
int main(int argc,char *argv[])
{
Derived d;
Base &b = d;
d.f(1);
b.f(1);
return 0;
}
这个程序有问题吗?答:没有问题,能正确运行;
由于在Derived重新定义了f函数,覆盖了Base的f,并没有重新实现虚函数,所以d.f(1);调用Derived中重新定义的函数没有问题;
b.f(1);由于b的静态类型为Base,调用Base::f(int a)也是没有疑问的,所以运行结果和上例一样:
Derived f:para=1
Base f:para=1
总结,如果在子类中,重新定义了虚拟函数,或者重载了基类虚函数,那么将覆盖从子类继承来的同名虚函数,那么在调用函数的时候,将根据对象的静态类型来决定调用那个函数. - 例五
int main(int argc,char *argv[])
{
Derived d;
Base &b = d;
double value = 87.01;
d.f(value);
b.f(value);
return 0;
}
编译的时候,将会在d.f(value);报错误:error C2668: “Derived::f” : 对重载函数的调用不明确,二义性就如第一个例子那样产生了.因为value在这里不知道该转换成int还是long;
但是b.f(value);调用没有二义性,因为在Base空间只有一个f函数,虽然有警告,单在这个地方value只能转换成int类型,确定会调用Base::f(int a),所以编译器不会报错误.
在这儿,由于f(int)在子类中被重新定义,在Derived中重载了f(long),所以在这儿就存在了二义性.
在子类中千万不要随便重新定义基类继承过来的虚函数,造成基类继承下来的虚函数被覆盖.
c++函数重载二义性
最新推荐文章于 2021-10-15 18:25:45 发布