c++关于重载和虚函数的困惑。。。。(请高手指点)
看了钱能的书,邮电部明白的地方。
函数重载用一个同名字的函数实现不同的功能。
虚函数就是父类和子类都用到的一个同名函数,但是子类的对父类的函数又有补充。
我的头绪有点乱,他们肯定有区别,但是像不出来,拿未能给我讲讲,最好给一个例子。多谢多谢。
问题点数:10、回复次数:9Top
1 楼i_doit(呆呆兔)回复于 2002-04-05 12:12:05 得分 1
重载函数和虚拟函数都是实现多态性的方法。
重载函数是编译器在程序编译期间就根据函数参数列表的不同,产生了不同的函数代码,它是在编译期间就实现的多态性。
虚拟函数是在程序的执行期间,根据虚拟表中的数据来判断是应该调用哪一个类中定义的函数,它是在执行期间实现的多态性。Top
2 楼pyl2001(尚未开窍)回复于 2002-04-05 12:17:05 得分 0
虚函数是必须参数返回类型一样的吧,重载好像不用Top
3 楼coppermine(coppermine)回复于 2002-04-05 12:25:33 得分 1
区别在于:重载的函数虽然函数名相同,但是参数列表是不同的;而虚函数的函数名和参数列表是相同的;重载函数是静态联编的,虚函数是动态联编的;
重载函数不能实现多态,虚函数可以实现多态;Top
4 楼LionEagle(LionEagle)回复于 2002-04-05 12:28:53 得分 2
class A
{
public:
virtual void f(){ cout<<"A::f()"<<endl; }
};
class B : public A
{
public:
void f(){ cout<<"B::f()"<<endl; }
void g( int x ){ cout<<"B::g(int)"<<endl; }
void g( float x ){ cout<<"B::g(float)"<<endl; }
};
B中的f()是虚拟函数,两个g()函数是重载
A* pA;
A a;
B b;
pA = &b;
// 虚函数的使用
pA->f(); // call B::f()
b.f(); // call B::f();
a.f(); // call A::f();
// 重载函数的使用
b.g( 1 ); // call B::g(int)
b.g( 1.0 ); // call B::g(float)
对编程者而言,重载可以看成是多态的,因为同样的函数名称有不同的行为(但参数不同),但实际上编译器会重新改写重载函数的名称,使他们各不相同,比如上例中两个函数名称可能变成类似_g_int(int),_g_float(float)这样的东西。这和虚函数的多态是不一样的。Top
5 楼hhoking(妙手仁心)回复于 2002-04-05 12:41:11 得分 0
同意lioneagle(LionEagle)。Top
6 楼hellwolf(地狱狼)(活着)(死磕)回复于 2002-04-05 12:51:18 得分 2
重载的函数,返回类型可以不同,但参数类型不能改变
如:
class A{
A& f();
public:
void p(A&);
}
class B:public A{
B& f(); //it's fine
public:
void P(B&);//illegle,not fine
}Top
7 楼humanic_cn(文)回复于 2002-04-05 13:02:01 得分 2
我有点不同的意见
我谈一谈类成员函数的多态
首先,类成员函数的多态是为了解决调用类成员函数时出现多个匹配的问题,这是一个基本的原则,如下
class A
{
public:
void f(){}
//...
}
class B:public A
{
public:
void f(){}
//...
}
如果有如下调用
void test(A & x){}
编译器找到两个可以匹配的成员函数A::f()和B::f()
利用多态就能够很好的解决这个问题,只是将void f()换成virtual void f()即可,编译器遇到带有virtual的成员函数,不作处理,当运行时根据传入类的类型确定要调用的成员函数是A::f()和还是B::f(),这就是所说的滞后编译
但是,使用多态会增加内存的负担,所以经可能的不要随便使用,如果没有违反上述的原则,则可以不必使用多态,而且编译器也不会按多态来处理,比如:
class A
{
public:
void f(int i){}
//...
}
class B:public A
{
public:
void f(float i){}
//...
}
此时,成员函数的调用不会找到多个匹配的问题,所以不用重载
但是,有一个例外,如果重载的函数返回的是类本身的指针或者是引用,那么一定要用多态,代码如下:
class A
{
public:
virtual A * f(){}
//...
}
class B:public A
{
public:
virtual B * f(){}
//...
}
综上所述,最重要的是把握一个原则,那就是,在调用成员函数时,是不是匹配多个成员函数。
Top
8 楼bluewood_cn(蓝木头)回复于 2002-04-05 14:21:10 得分 2
我再补充几句:
重载会把基类所有同名函数的都覆盖掉
例如:
class A
{public:
void func(){cout<<"hello ";}
void func(int x){cout <<"i love u";}
};
class B:public A
{
public :
void func(){cout <<"in class b"}
}
int main()
{
A a;
B b;
a.func();
a.func(2);
b.func();
b.func(2);
}
输出结果应为:
hello
i love u
in class b
int class b
而不是
hello
i love u
in class b
i love u (因为你并不想改写函数int func(int x))
而虚函数就可以得到正确的输出
Top
9 楼humanic_cn(文)回复于 2002-04-09 12:42:41 得分 0
b.func(2);没有定义Top




