c++ 34 虚函数与多态一

来源:互联网 发布:淘宝卖鲜花资质 编辑:程序博客网 时间:2024/06/05 15:51

其中,虚函数 动态多态,其他静态多态




#include <iostream>using namespace std;class Base{public:virtual void Fun1(){cout<<"Base::Fun1.."<<endl;}virtual void Fun2(){cout<<"Bae::Fun2.."<<endl;}void Fun3(){cout<<"Base::Fun3"<<endl;}};class Derived:public Base{public:virtual void Fun1()//即使不加virtual 也是虚函数{cout<<"Derived::Fun1.."<<endl;}virtual void Fun2()//即使不加virtual 也是虚函数{cout<<"Derived::Fun2.."<<endl;}void Fun3(){cout<<"Derived::Fun3"<<endl;}};int main(void){Base* p;Derived d;p=&d;p->Fun1();p->Fun2();p->Fun3();return 0;}

打印结果

基类指针指向派生类对象。调用虚函数会调用实际指向的虚函数,而如果是普通的函数,就会根据指针的类型,来调用相应类的成员函数。

Fun1 是虚函数,基类指针指向派生类对象,调用的是派生类对象的虚函数。

是在运行使其确定的。



析构函数 怎么调用的?

#include <iostream>using namespace std;class Base{public:virtual void Fun1(){cout<<"Base::Fun1.."<<endl;}virtual void Fun2(){cout<<"Bae::Fun2.."<<endl;}void Fun3(){cout<<"Base::Fun3"<<endl;}~Base(){    cout<<"~Base.."<<endl;}Base(){  cout<<"Base.."<<endl;}};class Derived:public Base{public:virtual void Fun1()//即使不加virtual 也是虚函数{cout<<"Derived::Fun1.."<<endl;}virtual void Fun2()//即使不加virtual 也是虚函数{cout<<"Derived::Fun2.."<<endl;}void Fun3(){cout<<"Derived::Fun3"<<endl;}~Derived(){    cout<<"~Derived..."<<endl;}Derived(){    cout<<"Derived..."<<endl;}};int main(void){Base* p;p=new Derived;//基类指针指向派生类对象p->Fun1();delete p;//如果析构函数不是虚的。 根据p的指针类型来确定return 0;}



#include <iostream>using namespace std;class Base{public:virtual void Fun1(){cout<<"Base::Fun1.."<<endl;}virtual void Fun2(){cout<<"Bae::Fun2.."<<endl;}void Fun3(){cout<<"Base::Fun3"<<endl;}virtual ~Base()//如果一个类要作为多态基类,要将析构函数,否则就存在内存泄漏,如果没有被其他类继承,就没有必要{    cout<<"~Base.."<<endl;}Base(){  cout<<"Base.."<<endl;}};class Derived:public Base{public:virtual void Fun1()//即使不加virtual 也是虚函数{cout<<"Derived::Fun1.."<<endl;}virtual void Fun2()//即使不加virtual 也是虚函数{cout<<"Derived::Fun2.."<<endl;}void Fun3(){cout<<"Derived::Fun3"<<endl;}~Derived()//这里不加也是虚函数 base 有加{    cout<<"~Derived..."<<endl;}Derived(){    cout<<"Derived..."<<endl;}};int main(void){Base* p;p=new Derived;//基类指针指向派生类对象p->Fun1();delete p;//如果析构函数不是虚的。 根据p的指针类型来确定return 0;}


派生类的析构函数也会被调用。


如何实现动态绑定的?


#include <iostream>using namespace std;class Base{public://即使这里修改成为private,也能访问。因为这里是根据内存模型推算出来的。virtual void Fun1(){cout<<"Base::Fun1.."<<endl;}virtual void Fun2(){cout<<"Bae::Fun2.."<<endl;}int data1;};class Derived:public Base{public:virtual void Fun2()//即使不加virtual 也是虚函数{cout<<"Derived::Fun2.."<<endl;}virtual void Fun3()//即使不加virtual 也是虚函数{cout<<"Derived::Fun3.."<<endl;}int data2;};typedef void(*FUNC)();int main(void){cout<<sizeof(Base)<<endl; //8cout<<sizeof(Derived)<<endl;//12//基类只有一个数据成员,正常情况下,应该是4个字节?为什么是8个字节?//原因 是:头四个字节 存放指向虚表的指针 //虚表和虚基类表是不一样的。虚基类表实在虚继承的情况下产生的。//虚表存放的是什么呢?// 存放的是虚函数 这就是基类的内存模型。 //验证 基类Base b;long** p=(long**)&b;//对基类的地址做一个转换。指针的指针 存放的是一个指针,指针指向一个表格FUNC fun=(FUNC)p[0][0];//指向基类的虚函数  FUNC 函数指针类型fun();//调用 base: fun1 fun=(FUNC)p[0][1];fun();//调用base :fun2 //验证派生类cout<<"========"<<endl;Derived d;p=(long**)&d;fun=(FUNC)p[0][0];//base fun1fun();fun=(FUNC)p[0][1];//derived fun2fun();fun=(FUNC)p[0][2];//derived fun3fun();Base* pp=&d;//基类指针指向派生类对象,取出对象的头四个字节,取出虚表,在虚表中,调用Dervider的Fun2();,而不是基类的Fun2();从而达到动态绑定。调用派生类虚函数pp->Fun2();//运行时期决定函数的入口地址。cout<<"========"<<endl;//d.Fun2();//直接调用不会动态绑定 只能通过基类指针或者引用//虚函数为什么不能声明为静态?//静态函数没有this 指针。Base::Fun2();没有this 指针。不是对象的一部分。就没有办法取出 对象的头四个字节 虚表指针,就没法取出虚表。 同样友元也不行return 0;}


像上转型的时候存在对象切割的问题。派生类特有的成员消失了。

#include <iostream>using namespace std;class CObject{public:virtual void Serialize(){cout<<"CObject::Serialize"<<endl;}};class CDocument :public CObject{public:   int data1;   void func()   {      cout<<"Document::func..."<<endl;  Serialize();   }   virtual void Serialize()   {      cout<<"Document  Serialize"<<endl;   }};class CMyDoc :public CDocument{public:   int data2;   virtual void Serialize()   {      cout<<"CMyDoc  Serialize"<<endl;   } };int main(void){CMyDoc mydoc;CMyDoc* pmydoc=new  CMyDoc;cout<<"test1..."<<endl;mydoc.func();//Document::func..  CMyDoc  Serializecout<<"test2..."<<endl;((CDocument*)(&mydoc))->func();//Document::func..  CMyDoc  Serializecout<<"test3..."<<endl;//Document::func..  CMyDoc  Serializepmydoc->func();cout<<"test4..."<<endl;((CDocument)mydoc).func();//Document::func..  Document  Serialize  return 0;}

#include <iostream>using namespace std;class CObject{public:virtual void Serialize(){cout<<"CObject::Serialize"<<endl;}};class CDocument :public CObject{public:   int data1;   void func()   {      cout<<"Document::func..."<<endl;  Serialize();   }   virtual void Serialize()   {      cout<<"Document  Serialize"<<endl;   }   CDocument()//提供了拷贝构造函数,也必须要有默认构造函数 否则CMyDoc 在构造的时候,无法构造基类对象   {   }   CDocument(const CDocument& other)   {      cout<<" CDocument& other"<<endl;   }};class CMyDoc :public CDocument{public:   int data2;   virtual void Serialize()   {      cout<<"CMyDoc  Serialize"<<endl;   } };int main(void){CMyDoc mydoc;CMyDoc* pmydoc=new  CMyDoc;cout<<"test1..."<<endl;mydoc.func();//Document::func..  CMyDoc  Serializecout<<"test2..."<<endl;((CDocument*)(&mydoc))->func();//Document::func..  CMyDoc  Serializecout<<"test3..."<<endl;//Document::func..  CMyDoc  Serializepmydoc->func();cout<<"test4..."<<endl;((CDocument)mydoc).func();//Document::func..  Document  Serialize//这里mydoc 对象强制转换为CDocument 对象,向山转型。派生类特有成员消失//就连虚表也发生了变化. 完完全全将派生类对象转化为了基类对象//CDocument会调用拷贝构造函数  return 0;}



0 0
原创粉丝点击