您的位置:首页 > 编程语言 > C语言/C++

c++ 34 虚函数与多态一

2014-11-24 21:47 162 查看


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





#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; //8
cout<<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 fun1
fun();
fun=(FUNC)p[0][1];//derived fun2
fun();
fun=(FUNC)p[0][2];//derived fun3
fun();

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  Serialize
cout<<"test2..."<<endl;
((CDocument*)(&mydoc))->func();//Document::func..  CMyDoc  Serialize
cout<<"test3..."<<endl;//Document::func..  CMyDoc  Serialize
pmydoc->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  Serialize
cout<<"test2..."<<endl;
((CDocument*)(&mydoc))->func();//Document::func..  CMyDoc  Serialize
cout<<"test3..."<<endl;//Document::func..  CMyDoc  Serialize
pmydoc->func();
cout<<"test4..."<<endl;
((CDocument)mydoc).func();//Document::func..  Document  Serialize
//这里mydoc 对象强制转换为CDocument 对象,向山转型。派生类特有成员消失
//就连虚表也发生了变化. 完完全全将派生类对象转化为了基类对象
//CDocument会调用拷贝构造函数
return 0;
}


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: