C++ 多态知识点综合整理

多态的前提条件部分整理

  1. 子类继承
  2. 父类指针或者引用
  3. 虚函数(virtual <类名><函数名>(参数))
    在纯面向对象语言中,所有的函数都是多态的,而像C++这样的混合语言,函数既可以是多态的也可以是非多态的,这要由绑定的实际是编译时刻还是运行时刻来决定
//本类为多态前提条件的案例
#include <iostream>
using namespace std;
class TradesPerson
{  public:
        virtual void sayHi()
        {   cout<<"hi."<<endl;  }
};
class Tinker : public TradesPerson
{  public:
        virtual void sayHi()
        {   cout<<"I tinker."<<endl;    }
};
class Tailor : public TradesPerson
{  public:
        virtual void sayHi()
        {   cout<<"I tailor."<<endl;    }
};
int main()
{   TradesPerson*  p;
    int which;
    do  {
        cout<<"1 == TradesPerson, 2 == Tinker, 3 == Tailor";
        cin>>which;
    } while (which < 1 || which > 3);
    switch (which)
    {   case 1 : p = new TradesPerson; break;
        case 2 : p = new Tinker; break;
        case 3 : p = new Tailor; break;
    }
    p->sayHi();  //动态绑定
    //此处用来实施对sayHi的调用
    delete p;
    return 0;
}

基类型的指针数组,用随机数决定生成那个对象!

#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;
class TradesPerson
{ public:
    virtual void sayHi()  {cout<<"Just hi."<<endl;}
};
class Tinker : public TradesPerson
{ public:
    virtual void sayHi()  {cout<<"Hi, I tinker."<<endl;}
};
class Tailor : public TradesPerson
{ public:
    virtual void sayHi()  {cout<<"Hi, I tailor."<<endl;}
};

int main()  {
     srand( (unsigned) time( NULL ) ); //Sets a random starting point.
     TradesPerson*  ptrs[10];  
     unsigned  which , i ;

    for (i=0; i<10; i++) {
         which = 1 + rand() % 3;
        switch (which) {
          case 1 : ptrs[i] = new TradesPerson; break;
          case 2 : ptrs[i] = new Tinker; break;
          case 3 : ptrs[i] = new Tailor; break;
       }
   }

   for (i=0; i<10; i++) {
       ptrs[i] -> sayHi();
       delete  ptrs[ i ];
   }
   return 0;
}

当声明了基类的一个成员函数为虚函数的时候,即使该成员函数没有在派生类中被显示的声明为虚函数,但是它所在的派生类中也将自动成为虚函数。
如果虚函数在类声明之外定义的,关键字vitual仅仅在声明的时候需要,在定义的时候可以不写。
注意:C++仅仅允许将成员函数定义为虚函数,不能将顶层函数定义为虚函数。

virtual void f();   //error
int main(){
    .......
}

以下是个例子

#include <iostream>
using namespace std;
class High
{  protected:
     float H;
   public:
     High(float h) 
        {  H=h;}
     virtual void Show()    //在基类中定义虚函数Show()
        {  cout<<"High="<<H<<endl;}
};
class Cuboid:public High
{  private:
     float Length,Width;
   public:
     Cuboid(float l=0,float w=0,float h=0):High(h)
     {  Length=l; Width=w;}
   virtual void Show()  //在长方体派生类中定义虚函数Show()
     {  cout<<"Length="<<Length<<'\t';
        cout<<"Width="<<Width<<'\t';
        cout<<"High="<<H<<'\n'; 
        cout<<"Cuboid Volume="<<Length*Width*H<<endl;
     }    
};
class Cylinder:public High
{  private:
     float R;
   public:
     Cylinder(float r=0,float h=0):High(h)
     {R=r;}
    virtual void Show()  //在圆柱体派生类中定义虚函数Show()
     {  cout<<"Radius="<<R<<'\t';
        cout<<"High="<<H<<'\n';
        cout<<"Cylinder Volume="<<R*R*3.1415*H<<endl;
     }  
};
void main(void)
{  High h(10),*p;
   Cuboid  cu(10,10,10);
   Cylinder cy(10,10);

   h.Show();
   cu.Show();
   cy.Show();

   p=&h;
   p->Show();

   p=&cu;
   p->Show();

   p=&cy;
   p->Show();
}

虚函数也是可以继承的!!!

class A{
    public:
        virtual void sayHello(){cout<<"Hello"<<end1}
}
class B : public A{

}
int main(){
    B b;
    b.sayHello();
}
//结果输出Hello

构造函数不能是虚函数,但是析构函数可以是虚函数。

class A {
public: 
    virtual A();//Error
    virtual A(int);//Error
    virtual ~A();//Right
    virtual void m();
}

原因在于虚拟调用是一种能在给定信息下不完全的情况下的工作机制。虚拟允许调用某个函数,对于这个函数,仅仅知道他的接口,而不知道具体的类型。但是要创建一个对象,必须要拥有完全的信息,需要知道建立的对象的具体类型。

虚析构函数确实很有必要的,看下这段代码
#include <iostream>
using namespace std;
class A {
    public:
        A() { cout<<endl<<"A() firing"<<endl; //*p = new char[5]; 
        };
        ~A() {  cout<<"~A() firing"<<endl;    //delete [ ] p;
        }
    private:
        char* p;
};
class Z : public A  
{   public:
        Z() {  
            cout<<"Z() firing"<<endl;
            //q = new char[5000]; 
        };
        ~Z() {  
            cout<<"~Z() firing"<<endl;     
            //delete  [ ] q; 
        }
    private:
        char*  q;
};
void  f()
{   A*  ptr; 
    ptr  =  new  Z();
    //delete  ptr;  
}
int main() 
{   for  (unsigned i = 0; i<3; i++)  f();
    return 0;
}

如果说析构函数不是虚成员函数的话,那么编译器实施静态绑定!!!
结果会造成内存泄漏!!!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值