什么函数不能是虚函数?为什么析构必须是虚函数?

Posted 白龙码~

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了什么函数不能是虚函数?为什么析构必须是虚函数?相关的知识,希望对你有一定的参考价值。

文章目录

虚函数

虚函数:被virtual修饰的基类成员函数。

纯虚函数:

  • 例如virtual void foo() = 0。纯虚函数所在类称为**“抽象类”**,抽象类不能实例化出对象,它的子类必须重写纯虚函数,否则依然是抽象类。
  • 纯虚函数可以有函数体,但是没有意义。

注:只在子类中声明virtual,无法构成虚函数。

不能声明为虚函数的函数

1、普通函数
普通函数不属于类。

2、构造函数
虚函数是为了依据不同的对象来产生不同的状态,但是前提是得有这个对象,而对象的产生必须依靠构造函数;其次,虚函数表指针的初始化也在构造函数的初始化列表阶段,二者矛盾了。

3、内联成员函数
内联函数是在编译期间直接在调用位置展开代码,而虚函数是在运行时通过不同对象来判断函数的调用;其次,内联函数没有地址,不能形成虚表。

4、静态成员函数
static成员函数是类的所有对象共享的,而虚函数是针对不同对象构成多态,二者矛盾;其次,静态成员函数没有this指针,无法访问虚函数表。

5、友元函数
友元函数不属于类的成员函数,不能被继承,更不能声明为虚函数。

协变

虚函数重写必须满足:返回值类型、函数名、参数列表都相同,但是协变和析构函数是例外。

如果基类的虚函数返回的是一个基类的指针或引用,派生类的虚函数返回的是一个派生类的指针或引用,那么这两个函数尽管返回值类型不同,但是依然构成虚函数,这种称为协变

而虚构函数会被编译器统一命名为destructor,因此满足虚函数的条件。

构造函数/析构函数内部可以调用虚函数实现多态吗

语法上支持,但是会失去多态的效果,因为:

  • 构造子类先调用父类的构造函数,相当于父类构造时子类还完全不存在,没有虚函数表指针也就无法构成多态。
  • 析构子类则先调用子类的析构函数,然后调用父类的。那么当父类析构时子类依旧不存在,所以无法构成多态。

为什么有的析构函数必须设置成虚函数

如果基类的析构函数是用virtual修饰的虚函数,那么无论派生类的析构函数是否有virtual修饰,它都是虚函数。原因是:

  1. 只要基类虚函数有virtual修饰,那么派生类的virtual可以省略。
  2. 析构函数的名称会被编译器统一处理成destructor,因此它们完全满足名称、参数列表、返回值类型相同的条件。

在如下情况,第二点格外重要:

class A
public:
	~A() 
;
class B :public A
public:
	B()  
		_a = new int[100]; 
	
	~B()  
        delete[]_a; 
    
private:
	int* _a;
;
int main()
	A* p = new B;
	delete p;
	return 0;

如果析构函数不定义成虚函数,那么这里就构成不了多态,我们delete p只会调用p类型的析构函数,即~A(),而B中new的空间就造成了内存泄漏。

以上是关于什么函数不能是虚函数?为什么析构必须是虚函数?的主要内容,如果未能解决你的问题,请参考以下文章

为什么析构函数必须是虚函数?为什么C++默认的析构函数不是虚函数

构造函数和析构函数可以是虚函数吗

构造函数和析构函数可以是虚函数吗

C++ 构造函数不能是虚函数,基类析构函数应该为虚函数

类中的析构函数是否是虚函数

基本语言