文章详情

  • 游戏榜单
  • 软件榜单
关闭导航
热搜榜
热门下载
热门标签
php爱好者> php文档>联编和虚函数

联编和虚函数

时间:2010-11-19  来源:osullishuai80

一、联编
(1)联编是指一个计算机程序自身彼此关联的过程,可分为静态联编和动态联编.
(2)静态联编
   联编工作出现在编译连接阶段,这种联编又称作早期联编,因为联编过程是在程序开始之前完成的.
(3)动态联编
   编译程序在编译阶段并不能确切知道将要调用的函数,只有在程序运行时才能确定将要调用的函数,这要求联编工作要在程序运行时进行,这种在程序运行时进行联编工作称作动态联编
   例程:
   #include <iostream.h>
   class Base
  {     
     public:    
        void fun()
       {
           cout<<"In Base class!"<<endl;
       }
  };
  class SubClass:public Base
  {     
     public:     
        void fun()
       {
           cout<<"In SubClass!"<<endl;
       }
  };
  class SubClass2:public Base
  {      
     public:     
        void fun()
       {
           cout<<"In SubClass2!"<<endl;
       }
  };
  
  void test(Base &b)
  {
     b.fun();
  }
  int main()   
  { 
     Base bc;
     SubClass sc;
     cout<<"Call test(bc)"<<endl;
     test(bc);
     cout<<"Call test(sc)"<<endl;
     test(sc);
  }
  执行结果:
     Call test(bc)
     In Base class!
     Call test(sc)
     In Base class!
Attention!!!
    函数test()的形参是类Base的别名,因此无论传递什么类型的参数,都会执行类Base的成员函数fun(),而不会执行派生类的成员函数fun().但程序员的意思是要执行派生类的成员函数fun(),执行结果明显偏离了程序员的意思.在C++中有没有什么机制可以阻止这种情况的发生呢?这就是虚函数.
  二、虚函数
(1)虚函数的定义
   虚函数是非static型的成员函数.在C++中它的定义格式是:
       virtual <类型说明符><函数名>(<参数表>)
(2)虚函数的应用场合
   当基类的引用(或指针)指向某个派生类对象时,若不使用虚函数,则调用时都会调用基类中定义的函数,如上例中程序会调用基类中的函数fun(),而不会调用派生类的成员函数fun().为此,需要明确三个前提,只有这三个前提满足时才会使用虚函数.
   <1>在基类中派生出派生类
   <2>基类的引用(或指针)指向派生类的某个对象
   <3>在派生类中存在和基类中相同的函数
      1.派生类中与基类虚函数有相同的参数个数
      2.派生类中该函数的参数类型与基类的虚函数的对应参数类型相同
      3.派生类中该还念书的返回值与基类函数相同
   此时,可以将基类中的该函数定义为虚函数,当基类的引用(或指针)指向不同的派生类对象时,则会调用其真正指向对象的成员函数而不是基类中定义的成员函数.  
Attention!!!
1.满足上述条件的派生类成员函数自然是虚函数,因此可以不必加virtual说明.
2.为什么满足了上述三个条件时必须使用虚函数?这是因为在基类和派生类中具有相同的函数(返回值类型、参数个数、参数类型),而派生类空间是对基类空间的继承,此时在派生类空间内有两个完全相同的函数.在派生类中的内存中如何分辨呢,通常有两种方法.一种是使用作用域运算符("::")唯一标识并分别访问.二是将从基类中继承的成员对象设置为虚函数.在下例中,派生类空间内既有基类的成员函数fun(),也有派生类自己的成员函数fun(),程序员可通过上述两种方法来区分这两个函数.
   例程:
   #include <iostream.h>
   class Base
  {     
     public:    
       virtual void fun()  //定义与派生类函数fun()相同的基类中函数fun()为虚函数
      {
          cout<<"In Base class!"<<endl;
      }
  }; 
  class SubClass:public Base
  {     
     public:     
        void fun()  //与基类中的虚函数完全相同(返回值类型、参数个数、参数类型)
       {
           cout<<"In SubClass!"<<endl;
       }
  };
 
  void test(Base &b)  //函数参数为基类的引用
  {
      b.fun();
  }
  int main()   
  { 
      Base bc;
      SubClass sc;
      cout<<"Call test(bc)"<<endl;
      test(bc);
      cout<<"Call test(sc)"<<endl;
      test(sc);      //基类Base引用(或指针)指向派生类SubClass的对象sc
   }
   执行结果:
      Call test(bc)
      In Base class!
      Call test(sc)
      In SubClass!
   
三、抽象类和纯虚函数
(1)纯虚函数是一种特殊的虚函数,它的一般格式如下:
       class <类名>
       {
          virtual <类型><函数名>(<参数表>)=0;
       }   
(2)抽象类:带有纯虚函数的类称作抽象类.
   1.抽象类不能创建对象.
   2.抽象类只能作为基类来使用,其纯虚函数的实现由派生类给出.若派生类中没有重定义纯虚函数,则该派生类仍为抽象类.
    例程:
    #include <iostream.h>
    class Vehicle   
   {     
      protected:     
         float speed;   
         int total;   
      public:    
         Vehicle(float speed,int total)   
         {    
            Vehicle::speed = speed;   
            Vehicle::total = total;    
         }   
         virtual void ShowMember()=0;    //定义纯虚函数  
   };      
   class Car:public Vehicle     
   {     
      protected:     
         int aird;
      public:     
         Car(int aird,float speed,int total):Vehicle(speed,total)     
        {     
             Car::aird = aird;      
        }   
         virtual void ShowMember()//=0;//派生类成员函数重载 
        {   
             cout<<speed<<"|"<<total<<"|"<<aird<<endl;   
        }        
   };     
  
   int main()   
   { 
       //Vehicle a(100,4);  //错误,抽象类不能创建对象  
       Car b(250,150,4); 
       b.ShowMember(); 
       return 0;
   }
Attention!!!
1.抽象类不能创建某个具体的对象.
2.若在派生类中写成"virtual void ShowMember()=0",则该派生类仍为抽象类,同样也不能创建某个具体的对象.
  四、虚析构函数
(1)在析构函数前面加上关键字virtual进行说明,称该析构函数为虚析构函数.
(2)构造函数不能是虚函数.
(3)若一个基类的析构函数被说明为虚析构函数,则它的派生类中的析构函数也是虚函数.
(4)说明虚析构函数目的在于使用delete运算符删除一个对象时,能保证析构函数被正确的执行.因为设置虚析构函数后,可以采用动态联编的方式选择析构函数.
   例程:
   #include <iostream.h>
   #include <stdlib.h>
   class ClxBase
   {
      public:
         ClxBase()      //基类构造函数
        {
           cout<<"construct Base class!"<<endl;
        };
        virtual ~ClxBase() {cout<<"in destructor of class ClxBase"<<endl;};      //虚析构函数
        virtual void DoSomething(){cout<<"Do something in class ClxBase!"<<endl;};//虚函数
      //void DoSomething() { cout << "Do something in class ClxBase!" << endl; };
   };
   class ClxDerived : public ClxBase
   {
       public:
          ClxDerived()//派生类构造函数
         {
             cout<<"construct Sub class!"<<endl;
         };
         ~ClxDerived() {cout<<"Output from the destructor of class ClxDerived!"<<endl;};//虚析构函数
         void DoSomething()//与基类的虚函数相同(返回值类型、参数个数、参数类型)
        {
             cout << "Do something in class ClxDerived!" << endl;
        };
   };
   void main()
   {
       ClxBase *pTest = new ClxDerived;  //创建一指向派生类的基类指针
       pTest->DoSomething();          //执行派生类的相应的函数
       delete pTest;                 //删除派生类的对象
 }
 执行结果:
     construct Base class!
     construct Sub class!
     Do something in class ClxDerived!
     Output from the destructor of class ClxDerived!
     in destructor of class ClxBase
Attention!!!
(1)第一条语句:
   创建一指向派生类的基类指针,此时符合需要创建虚函数的三个条件,即:
    1.由基类派生出派生类
    2.基类的指针指向派生类的某个对象
    3.在派生类中存在和基类中相同的函数void DoSomething(),即返回值类型、参数个数、参数类型均相同.
(2)第二条语句:
   通过基类的指针来调用派生类的函数void DoSomething(),由于符合创建虚函数的三个条件,因此必须将基类中的函数void DoSomething()定义为虚函数,这样通过该指针才能正确的调用派生类的函数void DoSomething(),否则仍调用的是基类的函数void DoSomething().因此,若执行基类中被屏蔽的语句,则输出结果为:
        construct Base class!
        construct Sub class!
        Do something in class ClxBase!
        Output from the destructor of class ClxDerived!
        in destructor of class ClxBase
(3)第三条语句:
    该语句删除了指向
 
相关阅读 更多 +
排行榜 更多 +
辰域智控app

辰域智控app

系统工具 下载
网医联盟app

网医联盟app

运动健身 下载
汇丰汇选App

汇丰汇选App

金融理财 下载