c++虚函数、虚析构函数

虚函数

作用:

在基类中定义了虚函数后,可以在派生类中重新定义该虚函数,但在重新定义时,其返回类型、函数名、参数个数、参数类型的顺序,都必须完全相同(即只有函数体可以不同)。

显示定义

格式:

virtual 返回类型 函数名(参数){函数体;}

代码示例: 

#include <iostream>
#include <string>
using namespace std;
class say_basic
{
public:
	string word;
	say_basic(string default_word = "human") :word(default_word){}
	virtual void say_something() {
		cout << "hellow " <<  word << endl;
	}
	string get_type() {
		return word;
	}
};

class say_basic1: public say_basic
{
public:
	say_basic1(string default_word = "man") : say_basic(default_word){}
	void say_something() 
	{
		cout << "hi "  << word << endl;
	}

};
int main()
{
	say_basic *p;
	say_basic  f;
	say_basic1 word1;
	p = &f;
	p -> say_something();
	p = &word1;
	p -> say_something();
}

运行结果:

虚函数的隐式定义

若在函数前没有virtual声明,系统会通过判断不同类中的同名函数的返回类型、参数个数、参数类型顺序、满足赋值兼容的指针来进行virtual虚函数的隐式定义。

说明

使用对象名和点运算符的方式也可以调用虚函数,如mom.like()可以调用虚函数Mother::like()。但是,这种调用是在编译时进行的静态连编,它没有充分利用虚函数的特性,只有通过基类指针访问虚函数时才能获得运行时的多态性。

 虚析构函数

定义一个基类的指针,用new创建一个派生类的无名对象, 再将这个无名对象的地址赋给指针后,运用delete运算符撤销无名对象时,会执行基类的析构函数,而不是派生类的。

say_basic* p;
p = new say_basic1;
delete p;//此时会调用基类say_basic的析构函数进行删除

原因

撤销指针所指的派生类的无名对象,调用析构函数时,采用了静态连编方式,只调用了基类Base的析构函数。

 此时虚析构函数就用于解决该问题,即先调用派生类的析构函数

需要再基类中的析构函数定义时声明virtual,格式如下:

virtual ~派生类名(){}

 示例:

#include <iostream>
#include <string>
using namespace std;
class say_basic
{
public:
	virtual ~say_basic()
	{
		cout << "基类析构函数调用" << endl;
	}
	string word;
	say_basic(string default_word = "human") :word(default_word){}
	virtual void say_something() {
		cout << "hellow " <<  word << endl;
	}
	string get_type() {
		return word;
	}
};

class say_basic1: public say_basic
{
public:
	~say_basic1()
	{
		cout << "派生类析构函数调用" << endl;
	}
	say_basic1(string default_word = "man") : say_basic(default_word){}
	void say_something() 
	{
		cout << "hi "  << word << endl;
	}

};
int main()
{
	say_basic* p;
	p = new say_basic1;
	delete p;//此时会先调用派生类say_basic1的析构函数
}

结果:

纯虚函数

在声明虚函数时被初始化为0的函数,定义格式:

virtual 函数类型 函数名(参数) = 0

 作用:

是在基类中为其派生类保留一个函数的名字,以便派生类根据需要重新定义。

抽象类

定义:当一个类中至少有一个纯虚函数,则该类为抽象类。

抽象类相关规定:

1、抽象类只能作为基类来使用,不能建立抽象类对象。
2、不允许从具体类派生出抽象类。所谓具体类,就是不包含纯虚函数的普通类。
3、抽象类不能用作函数的参数类型、函数的返回类型或是显式转换的类型。
4、可以声明指向抽象类的指针或引用,此指针可以指向它的派生类,进而实现多态性。
5、如果派生类中没有定义纯虚函数的实现,而派生类中只是继承基类的纯虚函数,则这个派生类仍然是一个抽象类。如果派生类中给出了基类纯虚函数的实现,则该派生类就不再是抽象类了,它是一个可以建立对象的具体类了。

整合示例:求面积

#include <iostream>
using namespace std;

/*** 定义一个公共基类 ***/
class Figure{
protected:
	double x, y;
public:
	Figure(double a, double b): x(a), y(b) {  }
	virtual void getArea()      //虚函数
	{  
		cout << "No area computation defind for this class.\n";
	}
};

class Triangle: public Figure{
public:
	Triangle(double a, double b): Figure(a, b){  }
	//虚函数重定义,用于求三角形的面积
	void getArea(){
		cout << "Triangle with height " << x << " and base " << y;
		cout << " has an area of " << x * y * 0.5 << endl;
	}
};

class Square: public Figure{
public:
	Square(double a, double b): Figure(a, b){  }
	//虚函数重定义,用于求矩形的面积
	void getArea(){
		cout << "Square with dimension " << x << " and " << y;
		cout << " has an area of " << x * y << endl;
	}
};

class Circle: public Figure{
public:
	Circle(double a): Figure(a, a){  }
	//虚函数重定义,用于求圆的面积
	void getArea(){
		cout << "Circle with radius " << x ;
		cout << " has an area of " << x * x * 3.14 << endl;
	}
};

int main(){
	Figure *p;
	Triangle t(10.0, 6.0);
	Square s(10.0, 6.0);
	Circle c(10.0);

	p = &t;
	p->getArea();
	p = &s;
	p->getArea();
	p = &c;
	p->getArea();

	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值