虚函数学习

今天真是收获不少,又把虚函数折腾了一遍。看着看着,似乎多明白了点什么。照例,网上有朋友写的很好的总结文章,原链接:http://blog.csdn.net/jackystudio/article/details/11895639

原文:

虚函数的作用和意义,就不进行说明了,这里主要讨论下虚函数的用法。


1.典型的虚函数用法

可以看到,只有标识为virtual的函数才会产生运行时多态的效果。它只能借助指针或者引用来达到多态的效果。

  1. class A  
  2. {  
  3. public:  
  4.     virtual void f(){cout<<"A::f()";}//虚函数   
  5.     void g(){cout<<"A::g()";}//普通函数   
  6. };  
  7.   
  8. class B :public A{  
  9. public:  
  10.     virtual void f(){cout<<"B::f()";}  
  11.     void g(){cout<<"B::g()";}  
  12. };  
  13.   
  14. class C :public A{  
  15. public:  
  16.     virtual void f(){cout<<"C::f()";}  
  17.     void g(){cout<<"C::g()";}  
  18. };  
  19.   
  20. int _tmain(int argc, _TCHAR* argv[])  
  21. {  
  22.     A* pa=new B;//pa是指针喔   
  23.     pa->f(); // 调用B::f()   
  24.     pa->g(); // 调用A::g()   
  25.     delete pa;  
  26.   
  27.     pa=new C;  
  28.     pa->f(); // 调用C::f()   
  29.     pa->g(); // 调用A::g()   
  30.     delete pa;  
  31.   
  32.     pa=NULL;  
  33.     return 0;  
  34. }  
class A
{
public:
	virtual void f(){cout<<"A::f()";}//虚函数
	void g(){cout<<"A::g()";}//普通函数
};

class B :public A{
public:
	virtual void f(){cout<<"B::f()";}
	void g(){cout<<"B::g()";}
};

class C :public A{
public:
	virtual void f(){cout<<"C::f()";}
	void g(){cout<<"C::g()";}
};

int _tmain(int argc, _TCHAR* argv[])
{
	A* pa=new B;//pa是指针喔
	pa->f(); // 调用B::f()
	pa->g(); // 调用A::g()
	delete pa;

	pa=new C;
	pa->f(); // 调用C::f()
	pa->g(); // 调用A::g()
	delete pa;

	pa=NULL;
	return 0;
}


2.虚函数的默认继承

虚函数是默认继承virtual属性的,即使在子类中没有标识virtual。

  1. class A  
  2. {  
  3. public:  
  4.     virtual void f(){cout<<"A::f()";}  
  5. };  
  6.   
  7. class B :public A{  
  8. public:  
  9.     void f(){cout<<"B::f()";}//不加virtual了   
  10. };  
  11.   
  12. class C :public B{  
  13. public:  
  14.     void f(){cout<<"C::f()";}//也不加virtual了   
  15. };  
  16.   
  17. int _tmain(int argc, _TCHAR* argv[])  
  18. {  
  19.     A* pa=new B;  
  20.     pa->f(); // 调用B:f()   
  21.     delete pa;  
  22.   
  23.     pa=new C;  
  24.     pa->f(); // 调用C:f()   
  25.     delete pa;  
  26.   
  27.     pa=NULL;  
  28.     return 0;  
  29. }  
class A
{
public:
	virtual void f(){cout<<"A::f()";}
};

class B :public A{
public:
	void f(){cout<<"B::f()";}//不加virtual了
};

class C :public B{
public:
	void f(){cout<<"C::f()";}//也不加virtual了
};

int _tmain(int argc, _TCHAR* argv[])
{
	A* pa=new B;
	pa->f(); // 调用B:f()
	delete pa;

	pa=new C;
	pa->f(); // 调用C:f()
	delete pa;

	pa=NULL;
	return 0;
}


3.纯虚函数

纯虚函数和Java中的接口很像了,因为纯虚函数的存在导致了该类成了抽象类,它的主要作用就是规范接口,把实现留给子类。如果子类没有实现它的所有虚函数,那么该子类也是一个抽象类,通用不能进行实例化。

  1. class A  
  2. {  
  3. public:  
  4.     virtual void f()=0;//纯虚函数,导致该类为抽象类   
  5. };  
  6.   
  7. class B :public A{  
  8. public:  
  9.     virtual void f(){cout<<"B::f()";}  
  10. };  
  11.   
  12. int _tmain(int argc, _TCHAR* argv[])  
  13. {  
  14.     //A* pa=new A;//出错,不能实例化抽象类   
  15.     A* pa=new B;  
  16.     pa->f();//调用B::f()   
  17.     delete pa;  
  18.   
  19.     pa=NULL;  
  20.     return 0;  
  21. }  
class A
{
public:
	virtual void f()=0;//纯虚函数,导致该类为抽象类
};

class B :public A{
public:
	virtual void f(){cout<<"B::f()";}
};

int _tmain(int argc, _TCHAR* argv[])
{
	//A* pa=new A;//出错,不能实例化抽象类
	A* pa=new B;
	pa->f();//调用B::f()
	delete pa;

	pa=NULL;
	return 0;
}


4.虚函数的调用模型

子类调用父类函数只有虚函数才得以执行,普通函数只会调用父类函数,不过要注意以下的h()可不能是构造函数或者析构函数,不然多态就无法实现。

  1. class A  
  2. {  
  3. private:  
  4.     virtual void f(){cout<<"A::f()"<<endl;}  
  5.     void g(){cout<<"A::g()"<<endl;}  
  6. public:  
  7.     void h(){f();g();}  
  8. };  
  9.   
  10. class B :public A{  
  11. private:  
  12.     virtual void f(){cout<<"B::f()"<<endl;}  
  13.     void g(){cout<<"B::g()"<<endl;}  
  14. };  
  15.   
  16. int _tmain(int argc, _TCHAR* argv[])  
  17. {  
  18.     B b;  
  19.     b.h();//调用父类的h(),分别再调用f()和g()。f()为虚函数调用子类B::f(),g()为普通函数调用父类A::g()。   
  20.   
  21.     return 0;  
  22. }  
class A
{
private:
	virtual void f(){cout<<"A::f()"<<endl;}
	void g(){cout<<"A::g()"<<endl;}
public:
	void h(){f();g();}
};

class B :public A{
private:
	virtual void f(){cout<<"B::f()"<<endl;}
	void g(){cout<<"B::g()"<<endl;}
};

int _tmain(int argc, _TCHAR* argv[])
{
	B b;
	b.h();//调用父类的h(),分别再调用f()和g()。f()为虚函数调用子类B::f(),g()为普通函数调用父类A::g()。

	return 0;
}

5.虚析构函数

虚构函数可以是虚函数,甚至是纯虚函数。如果它作为一个基类,那析构函数必须是虚函数。

而构造函数不能是虚函数。

  1. class A  
  2. {  
  3. public:  
  4.     A(){p_a=new char[1];cout<<"new 1"<<endl;}  
  5.     virtual ~A(){delete[] p_a;cout<<"delete 1"<<endl;}//正常   
  6.     //~A(){delete[] p_a;cout<<"delete 1"<<endl;}//异常,内存泄漏,~B()并没有被执行到   
  7. private:  
  8.     char* p_a;  
  9. };  
  10.   
  11. class B :public A{  
  12. public:  
  13.     B(){p_b=new char[2];cout<<"new 2"<<endl;}  
  14.     ~B(){delete[] p_b;cout<<"delete 2"<<endl;}//能不能正确执行~B()成了关键   
  15. private:  
  16.     char* p_b;  
  17. };  
  18.   
  19. int _tmain(int argc, _TCHAR* argv[])  
  20. {  
  21.     A* pa=new B;  
  22.     delete pa;  
  23.   
  24.     return 0;  
  25. }  
class A
{
public:
    A(){p_a=new char[1];cout<<"new 1"<<endl;}
	virtual ~A(){delete[] p_a;cout<<"delete 1"<<endl;}//正常
	//~A(){delete[] p_a;cout<<"delete 1"<<endl;}//异常,内存泄漏,~B()并没有被执行到
private:
	char* p_a;
};

class B :public A{
public:
	B(){p_b=new char[2];cout<<"new 2"<<endl;}
	~B(){delete[] p_b;cout<<"delete 2"<<endl;}//能不能正确执行~B()成了关键
private:
	char* p_b;
};

int _tmain(int argc, _TCHAR* argv[])
{
	A* pa=new B;
	delete pa;

	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值