为什么要用虚函数

似乎所有虚函数能做的事情,我都可以用函数重定义和调用父类版本的方式实现,那为什么还要用虚函数呢,它到底有什么优点... 似乎所有虚函数能做的事情,我都可以用函数重定义和调用父类版本的方式实现,那为什么还要用虚函数呢,它到底有什么优点 展开
 我来答
zybzyb1987
推荐于2017-12-16 · TA获得超过770个赞
知道答主
回答量:127
采纳率:0%
帮助的人:185万
展开全部
我也碰到过你类似的迷惑,特别是书上举的例子,让你越来越迷惑。事实上,你根本就无法想象那些作者的无知和愚蠢,举的垃圾例子给你感觉就是对知识的侮辱!
好了,下面我用一句话给你概括虚函数的作用,再用一个例子让你去体会。
1、基于向上类型转换,基类通过虚函数可以对多个子类相似的功能实现统一管理。
2、例子:
A为基类,B、C为A的同级子类。virtual只需在基类中标识一次,子类无需重复标识。
class A
{
virtual void display(){cout<<"我是A"<<endl;}
}
class B:public A
{
void display(){cout<<"我是B"<<endl;}
}

class C:public A
{
void display(){cout<<"我是C"<<endl;}
}

void display(A s)//以A类型作为参数的顶层函数,不同于类中的成员函数
{
s.display();//调用对象s的成员函数
}
int main()
{
A x1;
B x2;
C x3;
display(x1);//显示:我是A。
display(x2);//参数x2向上转换为x1类型,显示:我是B。
display(x3);//参数x3向上转换为x1类型,显示:我是C。
}
通过显示我们注意到以下两点:
1、尽管在顶层函数的定义中是以基类A作为其参数,但却能接受基类A的任一子类作为其参数。事实上,这是基于自动向上类型转换,即子类转换为它的父类型。
2、虽然子类转换成了它的父类型,但却可正确调用属于子类而不属于父类的成员函数。这是虚函数的功劳。
这样,我们通过设计一个以基类型作为参数的顶层函数,就可实现基类及其所有子类相似功能的统一管理,而不用理会不同对象自身的类型。
当然你还是可以利用域解析符去调用想要的成员函数,但情况并不总是那么顺利。当类层次很多时,你可能都不太记得你创建的对象属于哪个类型了。
中智咨询
2024-08-28 广告
在当今竞争激烈的商业环境中,企业需要不断提高自身的竞争力,以保持市场份额和增加利润。通过人效提升,企业可以更有效地利用有限的资源,提高生产力和效益,从而实现盈利目标。中智咨询提供全方位的组织人效评价与诊断、人效提升方案等数据和管理咨询服务。... 点击进入详情页
本回答由中智咨询提供
天枰小小怪5
2018-08-26
知道答主
回答量:2
采纳率:0%
帮助的人:1619
展开全部

维基百科的列子;

虚函数概念的引入可以解决这样的问题:

在面向对象程序设计中,派生类继承自基类。使用指针或引用访问派生类对象时,指针或引用本身所指向的类型可以是基类而不是派生类。如果派生类覆盖了基类中的方法,通过上述指针或引用调用该方法时,可以有两种结果:

  • 调用到基类的方法:编译器根据指针或引用的类型决定,称作“早绑定”;

  • 调用到派生类的方法:语言的运行时系统根据对象的实际类型决定,称作“迟绑定”。

  • 虚函数的效果属于后者。如果问题中基类的函数是“虚”的,则调用到的都是最终派生类(英语:most-derived class)中的函数实现,与指针或引用的类型无关。反之,如果函数非“虚”,调用到的函数就在编译期根据指针或者引用所指向的类型决定。

    有了虚函数,程序甚至能够调用编译期还不存在的函数。

    在 C++ 中,在基类的成员函数声明前加上关键字 virtual 即可让该函数成为 虚函数,派生类中对此函数的不同实现都会继承这一修饰符,允许后续派生类覆盖,达到迟绑定的效果。即便是基类中的成员函数调用虚函数,也会调用到派生类中的版本。

# include <iostream># include <vector>using namespace std;class Animal{public:
virtual void eat() const { cout << "I eat like a generic Animal." << endl; }
virtual ~Animal() {}};
class Wolf : public Animal{public:
void eat() const { cout << "I eat like a wolf!" << endl; }};
class Fish : public Animal{public:
void eat() const { cout << "I eat like a fish!" << endl; }};
class GoldFish : public Fish{public:
void eat() const { cout << "I eat like a goldfish!" << endl; }};

class OtherAnimal : public Animal{};
int main(){
std::vector<Animal*> animals;
animals.push_back( new Animal() );
animals.push_back( new Wolf() );
animals.push_back( new Fish() );
animals.push_back( new GoldFish() );
animals.push_back( new OtherAnimal() );

for( std::vector<Animal*>::const_iterator it = animals.begin();
it != animals.end(); ++it)
{
(*it)->eat();
delete *it;
}

return 0;}

以下是虚函数 Animal::eat() 的输出:

I eat like a generic Animal.
I eat like a wolf!
I eat like a fish!
I eat like a goldfish!
I eat like a generic Animal.

当 Animal::eat() 不是被宣告为虚函数时,输出如下所示:

I eat like a generic Animal.
I eat like a generic Animal.
I eat like a generic Animal.
I eat like a generic Animal.
I eat like a generic Animal.

已赞过 已踩过<
你对这个回答的评价是?
评论 收起
xingmou999
2010-10-22 · TA获得超过896个赞
知道小有建树答主
回答量:430
采纳率:0%
帮助的人:0
展开全部
虚函数这个东西的用处其实是比较大的。打个比方,有个父类中有个虚函数A,在B中调用这个A。两个继承类,一个重写A,一个不写,这样,在父类执行到B的时候,一个继承类就有的执行,一个就直接跳过A了。
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
lahzmhou
2010-10-22
知道答主
回答量:37
采纳率:0%
帮助的人:21.1万
展开全部
对的,通过函数重新定义个调用父函数是可以做的到得,但每次这样做不是很麻烦吗,有了虚函数每个子类在继承父类的基本属性外,同时还具有不同于其它子类的特点,这样代码的重用性不是提高了吗,也变得整洁了
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
ethanamy
2010-10-22
知道答主
回答量:13
采纳率:0%
帮助的人:13.2万
展开全部
虚函数主要是用来多态,在运行时,动态的决定执行哪个子类中的函数!
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
收起 更多回答(4)
推荐律师服务: 若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询

为你推荐:

下载百度知道APP,抢鲜体验
使用百度知道APP,立即抢鲜体验。你的手机镜头里或许有别人想知道的答案。
扫描二维码下载
×

类别

我们会通过消息、邮箱等方式尽快将举报结果通知您。

说明

0/200

提交
取消

辅 助

模 式