虚拟析构函数测试失败


#include <iostream>
#include <string>
using namespace std;
class Base {
    virtual ~Base() = default;
};
class Derived1 : protected Base {};
class Derived2 : protected Derived1{};
class Derived3 : protected Derived2{};
int main() {
    Base* b[] = {new Base, new Derived1, new Derived2, new Derived3};
    delete[] b;
    cin.get();
    return 0;
}

这给了我以下编译错误,我只是遵循了我所教的内容:

警告

1 警告 C4624:"Deferrd1":无法生成析构函数,因为基类析构函数不可访问或删除

警告 2

警告 C4624:"派生 2":无法生成析构函数,因为基类析构函数不可访问或删除

警告

3 警告 C4624:"Deferrd3":无法生成析构函数,因为基类析构函数不可访问或删除

错误

4 错误 C2243:"类型转换":存在从"派生 1 *"到"基本 *"的转换,但无法访问

错误

5 错误 C2243:"类型转换":从"派生 2 *"到"基本 *"的转换存在,但无法访问

错误

6 错误 C2243:"类型转换":存在从"派生3 *"到"基本 *"的转换,但无法访问

警告

7 警告 C4154:删除数组表达式;转换为提供的指针

8 智能感知:不允许转换为无法访问的基类"基">

9 智能感知:不允许转换为无法访问的基类"Dederd1">

10 智能感知:不允许转换为无法访问的基类"Derived2">

问题 1

将析构函数放在Basepublic部分中。

class Base {
    virtual ~Base() = default;
};

相当于:

class Base {
  private:
    virtual ~Base() = default;
};

将其更改为:

class Base {
  public:
    virtual ~Base() = default;
};

问题 2

Base* b[] = {new Base, new Derived1, new Derived2, new Derived3};

使用 new 运算符构造对象三次。您需要调用delete三次 - 每个指针一次。

而不是

delete[] b;

delete b[0];
delete b[1];
delete b[2];

问题 3

为了能够使用

Base* p = new Derived1;

你必须使Base成为Derived1public基类,而不是protected

改变

class Derived1 : protected Base {};
class Derived2 : protected Derived1{};
class Derived3 : protected Derived2{};

class Derived1 : public Base {};
class Derived2 : public Derived1{};
class Derived3 : public Derived2{};

你有三个大问题:

首先,您滥用了delete[].当您使用 new [] 分配数组时,将调用它。你还没有这样做。你需要遍历数组b,在每个元素上调用delete

其次,您的Base虚拟析构函数private。派生类型需要可以访问它,因此请使其public

第三,所以DerivedN是-Base,需要使继承public。否则,无法将指向派生对象的指针分配或初始化为指向 Base 的指针。

这是一个固定版本:

class Base {
 public:
    virtual ~Base() = default;
};
class Derived1 : public Base {};
class Derived2 : public Derived1{};
class Derived3 : public Derived2{};
int main()
{
    Base* b[] = {new Base, new Derived1, new Derived2, new Derived3};
    for (auto p : b) delete p;
}

最新更新