gpt4 book ai didi

c++ - 了解虚拟析构函数

转载 作者:太空狗 更新时间:2023-10-29 19:41:45 27 4
gpt4 key购买 nike

我试图让自己熟悉 OOP 概念,但不太理解 virtual 的概念。

  1. 可以创建虚拟析构函数,但不能创建虚拟构造函数。为什么?
  2. 如何在内部处理虚拟析构函数?我的意思是链接 Virtual Destructors说明了这个概念,但我的问题是如何调用 vtable(Derived 和 Base)的 vptr? (如果是虚成员函数,这种情况一般只调用Derived类的vptr指向的函数)
  3. 还有其他场景可能需要使用虚拟析构函数吗?

任何人都可以通过链接/示例帮助我理解上述概念吗?

最佳答案

首先简单介绍一下虚函数和非虚函数的区别:

代码中的每个非虚函数调用都可以在编译或链接期间解决。

resolved 是指函数的地址可以由编译器或链接器计算。

因此在创建的目标代码中,函数调用可以替换为用于跳转到该函数在内存中的地址的操作码。

使用虚函数,您可以调用只能在运行时解析的函数。

与其解释它,让我们运行一个简单的场景:

class Animal
{
virtual void Eat(int amount) = 0;
};

class Lion : public Animal
{
virtual void Eat(int amount) { ... }
};

class Tiger : public Animal
{
virtual void Eat(int amount) { ... }
};

class Tigon : public Animal
{
virtual void Eat(int amount) { ... }
};

class Liger : public Animal
{
virtual void Eat(int amount) { ... }
};

void Safari(Animal* animals[], int numOfAnimals, int amount)
{
for (int i=0; i<numOfAnimals; i++)
animals[i]->Eat(amount);
// A different function may execute at each iteration
}

正如您可能理解的那样,Safari 功能允许您灵活地喂养不同的动物。

但是由于直到运行时才知道每种动物的确切类型,因此要调用的确切 Eat 函数也是如此。


类的构造函数不能是虚函数,因为:

调用对象的虚函数是通过对象类的 V-Table 执行的。

每个对象都有一个指向其类的 V-Table 的指针,但这个指针仅在运行时,即创建对象时初始化。

换句话说,这个指针只有在调用构造函数时才被初始化,因此构造函数本身不能是虚的。

除此之外,构造函数首先是虚拟的是没有意义的。

虚函数背后的想法是,您可以在不知道调用它们的对象的确切类型的情况下调用它们。

当你创建一个对象时(即当你隐式调用构造函数时),你确切地知道你正在创建什么类型的对象,所以你不需要这种机制。


基类的析构函数必须是虚拟的,因为:

当你静态分配一个类继承自基类的对象时,那么在函数(如果对象是局部的)或程序(如果对象是全局的)结束时,类的析构函数会自动调用,然后调用基类的析构函数。

在这种情况下,析构函数是虚拟的这一事实没有任何意义。

另一方面,当您动态分配(new)一个类继承自基类的对象时,您需要动态释放(delete)它在程序执行的稍后时间。

delete 运算符采用指向对象的指针,其中指针的类型可能是基类本身。

在这种情况下,如果析构函数是虚拟的,则 delete 运算符会调用类的析构函数,而类的析构函数又会调用基类的析构函数。

但如果析构函数不是虚拟的,则 delete 运算符会调用基类的析构函数,而不会调用实际类的析构函数。

考虑以下示例:

class A
{
A() {...}
~A() {...}
};

class B: public A
{
B() {...}
~B() {...}
};

void func()
{
A* b = new B(); // must invoke the destructor of class 'B' at some later point
...
delete b; // the destructor of class 'B' is never invoked
}

关于c++ - 了解虚拟析构函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25780166/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com