欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

哪些函数不可以成为虚函数?构造函数和析构函数可以是虚函数吗?

程序员文章站 2022-03-15 16:33:25
...

哪些函数不能成为虚函数?

  1. 普通函数:普通函数不属于成员函数,是不能被继承的。普通函数只能被重载,不能被重写,因此声明为虚函数没有意义。因为编译器会在编译时绑定函数。
  2. 构造函数:只有当调用了构造函数,这个对象才能产生,如果把构造函数写成虚函数,这时候我们的对象就没有办法生成。更别说用对象去调用了。所以构造函数不能成为虚函数。
  3. 静态成员函数:静态成员函数是属于类的,不依赖于对象调用,所以也不能成为虚函数。
  4. 友元函数:友元函数不属于类的成员函数,不能被继承。对于没有继承特性的函数没有虚函数的说法。
  5. 内联函数:内联函数在编译时就被展开,它不能产生函数符号,所以不能往虚表中存放,自然就不能成为虚函数。

析构函数作为虚函数---虚析构

当子类有在堆上申请空间的操作,那么父类指针在释放时无法调用到子类的析构函数,这时就会造成内存泄漏。

解决方式:将父类中的析构函数改为虚析构或者纯虚析构。

虚析构和纯虚析构都可以解决父类指针释放子类对象,都需要有具体的函数实现。

语法:

  • 虚析构:virtual ~类名(){}
  • 纯虚析构:virtual ~类名() = 0;
                      类名::~类名(){}

下面一个例子:

#include<iostream>
using namespace std;
 
class Animal {
public:
	Animal(){
		cout << "Animal 构造函数调用!" << endl;
	}
	virtual void Speak() = 0;
 
	/*//析构函数加上virtual关键字,变成虚析构函数
	virtual ~Animal(){
		cout << "Animal虚析构函数调用!" << endl;
	}*/
 
	virtual ~Animal() = 0; //纯虚析构函数 
};
 
Animal::~Animal(){
	cout << "Animal 纯虚析构函数调用!" << endl;
}
 
//和包含普通纯虚函数的类一样,包含了纯虚析构函数的类也是一个抽象类。不能够被实例化。
 
class Cat : public Animal {
public:
	Cat(string name){
		cout << "Cat构造函数调用!" << endl;
		m_Name = new string(name);
	}
	virtual void Speak(){
		cout << *m_Name <<  "小猫在说话!" << endl;
	}
	~Cat(){
		cout << "Cat析构函数调用!" << endl;
		if (this->m_Name != NULL) {
			delete m_Name;
			m_Name = NULL;
		}
	}
public:
	string *m_Name;
};
 
int main() {
	Animal *animal = new Cat("Tom");
	animal->Speak();
	delete animal;
	return 0;
}

总结:

  • ​ 虚析构或纯虚析构就是用来解决通过父类指针释放子类对象
  • ​ 如果子类中没有堆区数据,可以不写为虚析构或纯虚析构
  • ​ 拥有纯虚析构函数的类也属于抽象类

 

相关标签: C++语言特性