C++为什么需要把重新定义的函数定义为虚函数

C++为什么需要把重新定义的函数定义为虚函数,第1张

1不是不能定义,是定义了没意义。因为构造函数不被继承,而虚函数是要在派生类中重定义的2定义虚析构函数后,由于多态,当使用基类指针指向派生类对象时,会调用派生类的虚构函数,然后派生类的析构函数自动调用基本析构函数。不是虚的话,直接调用基类的析构函数了。如果派生类中有用new分配的内存,就无法释放了

虚函数必须是基类的非静态成员函数,其访问权限可以是protected或public,在基类的类定义中定义虚函数的一般形式:

  virtual

函数返回值类型

虚函数名(形参表)

  {

函数体

}

 虚函数的作用是实现动态联编,也就是在程序的运行阶段动态地选择合适的成员函数,在定义了虚函数后,可以在基类的派生类中对虚函数重新定义,在派生类中重新定义的函数应与虚函数具有相同的形参个数和形参类型。以实现统一的接口,不同定义过程。如果在派生类中没有对虚函数重新定义,则它继承其基类的虚函数。

  当程序发现虚函数名前的关键字virtual后,会自动将其作为动态联编处理,即在程序运行时动态地选择合适的成员函数。

  ([20101028]

注:下行语义容易使人产生理解上的偏差,实际效果应为:

  如存在:Base

->

Derive1

->

Derive2

及它们所拥有的虚函数func()

  则在访问派生类Derive1的实例时,使用其基类Base及本身类型Derive1,或被静态转换的后续派生类Derive2的指针或引用,均可访问到Derive1所实现的func()。)

  动态联编规定,只能通过指向基类的指针或基类对象的引用来调用虚函数,其格式:

  指向基类的指针变量名->虚函数名(实参表)

  或

基类对象的引用名

虚函数名(实参表)

  虚函数是C++多态的一种表现

  例如:子类继承了父类的一个函数(方法),而我们把父类的指针指向子类,则必须把父类的该函数(方法)设为virtual(虚函数)。

  使用虚函数,我们可以灵活的进行动态绑定,当然是以一定的开销为代价。

如果父类的函数(方法)根本没有必要或者无法实现,完全要依赖子类去实现的话,可以把此函数(方法)设为virtual

函数名=0

我们把这样的函数(方法)称为纯虚函数。

  如果一个类包含了纯虚函数,称此类为抽象类

虚函数的实例

  #include<iostreamh>

  class

Cshape

  {

public:

void

SetColor(

int

color)

{

m_nColor=color;}

  void

virtual

Display(

void)

{

cout<<"Cshape"<<endl;

}

  private:

  int

m_nColor;

  };

  class

Crectangle:

public

Cshape

  {

  public:

  void

virtual

Display(

void)

{

cout<<"Crectangle"<<endl;

}

  };

  class

Ctriangle:

public

Cshape

  {

  void

virtual

Display(

void)

{

cout<<"Ctriangle"<<endl;

}

  };

  class

Cellipse

:public

Cshape

  {

  public:

void

virtual

Display(void)

{

cout<<"Cellipse"<<endl;}

  };

  void

main()

  {

  Cshape

obShape;

  Cellipse

obEllipse;

  Ctriangle

obTriangle;

  Crectangle

obRectangle;

  Cshape

pShape[4]=

  {

&obShape,

&obEllipse,&obTriangle,

&

obRectangle

};

  for(

int

I=

0;

I<

4;

I++)

  pShape[I]->Display(

);

  }

  本程序运行结果:

  Cshape

  Cellipse

  Ctriangle

  Crectangle

条件

  所以,从以上程序分析,实现动态联编需要三个条件:

  1、

必须把动态联编的行为定义为类的虚函数。

  2、

类之间存在子类型关系,一般表现为一个类从另一个类公有派生而来。

  3、

必须先使用基类指针指向子类型的对象,然后直接或者间接使用基类指针调用虚函数。

A

简化程序,和纯虚函数没关系

B

消除二义性。正解, 虚基类是为了强调"这个类型的某些方法没有意义, 只是为了继承, 不要构造这种类型的对象"

C

提高运行效率 ,和纯虚函数没关系

D

减少目标代码,纯虚函数和空函数相比相差也就是几个字节, 如果这也算的话确实是减少了。

定义虚函数的目的是实现运行时的多态,如果你想让基类的指针或引用能够在运行时根据所指(或引用)的对象去调用基类或派生类的方法,而不是根据基类指针或引用的类型,那你就得用虚函数来实现了。

如果不用指针或引用的话,根据对象实例类型(只要不是抽象类)来调用基类或派生类的方法,但那不是多态。

c++的惯例:

如果基类和派生类都定义了相同的方法,最好把基类的方法定义成虚函数。

虚函数的作用在面向对象的C++语言中,虚函数(virtual function)是一个非常重要的概念。因为它充分体现了面向对象思想中的继承和多态性这两大特性,在C++语言里应用极广。比如在微软的MFC类库中,你会发现很多函数都有virtual关键字,也就是说,它们都是虚函数。难怪有人甚至称虚函数是C++语言的精髓。虚函数是指一个类中你希望重载的成员函数,当你用一个基类指针或引用指向一个继承类对象的时候,你调用一个虚函数,实际调用的是继承类的版本。——摘自MSDN这个定义说得不是很明白。MSDN中还给出了一个例子,但是它的例子也并不能很好的说明问题。我们自己编写这样一个例子:#i nclude "stdioh"#i nclude "conioh"class Parent{public:char data[20];void Function1();virtual void Function2(); // 这里声明Function2是虚函数}parent;void Parent::Function1(){printf("This is parent,function1\n");}void Parent::Function2(){printf("This is parent,function2\n");}class Child:public Parent{void Function1();void Function2();} child;void Child::Function1(){printf("This is child,function1\n");}void Child::Function2(){printf("This is child,function2\n");}int main(int argc, char argv[]){Parent p; // 定义一个基类指针if(_getch()=='c') // 如果输入一个小写字母cp=&child; // 指向继承类对象elsep=&parent; // 否则指向基类对象p->Function1(); // 这里在编译时会直接给出Parent::Function1()的入口地址。

  1、虚函数的概念

  虚函数是以virtual关键字声明的基类函数。如果在基类中将某个函数指定为virtual,并且派生类中有另外一个该函数的定义,则编译器将知道我们不想静态连接该函数。我们真正需要的是基于调用该函数的对象种类,在程序的特定位置选择调用哪一个函数。

  2、定义

  语法:virtual 函数返回类型 函数名(参数表) {函数体}

  虚函数必须是基类的非静态成员函数,其访问权限可以是private或protected或public,在基类的类定义中定义虚函数的一般形式:

  class基类名{

  

  virtual 返回值类型 将要在派生类中重载的函数名(参数列表);

  };

<pre t="code" l="cpp">#include <iostream>

using namespace std;

class CShape

{

public:

CShape(void)

{

}

~CShape(void)

{

}

virtual void area(void) = 0;

virtual void cir(void) = 0;

};

class CRectangle:public CShape

{

public:

CRectangle(int xx = 0,int yy = 0)

{

x = xx;

y = yy;

}

void area()

{

cout<<xy<<endl;

}

void cir()

{

cout<<2(x+y)<<endl;

}

private:

int x,y;

};

class CCircle:public CShape

{

public:

CCircle(int rr = 0)

{

r = rr;

}

void area()

{

cout<<2314r<<endl;

}

void cir()

{

cout<<314rr<<endl;

}

private:

int r;

};

int main()

{

CShape a = new CRectangle(1,2);

a->area();

a->cir();

CShape b = new CCircle(3);

b->area();

b->cir();

system("pause");

return 0;

}

欢迎分享,转载请注明来源:内存溢出

原文地址:https://www.54852.com/langs/13494436.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2025-09-01
下一篇2025-09-01

发表评论

登录后才能评论

评论列表(0条)

    保存