鱼C论坛

 找回密码
 立即注册
查看: 2101|回复: 5

[已解决]C++ 堆区类析构报错

[复制链接]
发表于 2023-4-20 21:27:06 | 显示全部楼层 |阅读模式
5鱼币
本帖最后由 Eden00 于 2023-4-20 22:45 编辑

补充,似乎问题出在继承,改变继承顺序后,就变成delete c0无法析构,是否有什么问题?

Annotation 2023-04-20 223958.png

如下代码,没有报错,但是每次运行到delete v0;(157行)的时候,会报错Exception has occurred.Unknown signal,请问是为啥?
谢谢!
  1. #include <iostream>

  2. #include <string>

  3. #include <cmath>

  4. #include <stdlib.h>

  5. #include <ctime>

  6. using namespace std;

  7. class CPU
  8. {

  9. public:
  10.     string cname;

  11.     virtual void calculate() = 0;
  12.     ~CPU()
  13.     {
  14.         cout << cname << " CPU is destructed" << endl;
  15.     }
  16. };

  17. class VideoCard
  18. {

  19. public:
  20.     string vname;

  21.     virtual void display() = 0;
  22.     ~VideoCard()
  23.     {
  24.         cout << vname << " video card is destructed" << endl;
  25.     }
  26. };

  27. class Memory
  28. {

  29. public:
  30.     string mname;

  31.     virtual void store() = 0;
  32.     ~Memory()
  33.     {
  34.         cout << mname << " memory is destructed" << endl;
  35.     }
  36. };

  37. class Supplier : public CPU, public VideoCard, public Memory
  38. {

  39.     string name;

  40.     void calculate()
  41.     {

  42.         cout << name << " CPU is calculating" << endl;
  43.     }

  44.     void store()
  45.     {

  46.         cout << name << " memory is stoing" << endl;
  47.     }

  48.     void display()
  49.     {

  50.         cout << name << " video card is displaying" << endl;
  51.     }

  52. public:
  53.     Supplier()
  54.     {

  55.         cout << "Supplier is structed without argument" << endl;
  56.     }

  57.     Supplier(string n) : name(n)
  58.     {

  59.         cout << "Supplier is structed with name as " << n << endl;
  60.     }

  61.     string SetName(string n)
  62.     {

  63.         cout << "Supplier name is set by Class Supplier as " << n << endl;

  64.         name = n;

  65.         return name;
  66.     }

  67.     string GetName()
  68.     {

  69.         return name;
  70.     }

  71.     ~Supplier()
  72.     {

  73.         cout << name << " supplier is destructed" << endl;
  74.     }
  75. };

  76. class Computer
  77. {

  78.     CPU *c0;

  79.     VideoCard *v0;

  80.     Memory *m0;

  81. public:
  82.     Computer(Supplier c, Supplier v, Supplier m)
  83.     {

  84.         c0 = new Supplier(c);

  85.         v0 = new Supplier(v);

  86.         m0 = new Supplier(m);

  87.         c0->cname = c.GetName();

  88.         v0->vname = v.GetName();

  89.         m0->mname = m.GetName();

  90.         cout << "This computer is assembled with " << c0->cname << " CPU, " << v0->vname

  91.              << " video card, " << m0->mname << " memory" << endl;
  92.     }

  93.     ~Computer()
  94.     {

  95.       /* if (c0 != NULL)
  96.         {
  97.             cout << c0->cname << endl
  98.                  << c0 << endl;
  99.             delete c0;

  100.             c0 = NULL;
  101.         }*/

  102.         if (v0 != NULL)
  103.         {
  104.             cout << v0->vname << endl
  105.                  << v0 << endl;
  106.             delete v0;

  107.             v0 = NULL;
  108.         }

  109.         if (m0 != NULL)
  110.         {

  111.             delete m0;

  112.             m0 = NULL;
  113.         }
  114.     }

  115.     void work()
  116.     {

  117.         c0->calculate();

  118.         v0->display();

  119.         m0->store();
  120.     }
  121. };

  122. void fun0()
  123. {

  124.     Supplier q0("Qualcom");

  125.     Supplier i0;

  126.     i0.SetName("Intel");

  127.     Supplier a0("AMD");

  128.     Computer c0(q0, i0, a0);

  129.     c0.work();
  130. }

  131. int main()
  132. {

  133.     fun0();

  134.     system("pause");

  135.     return 1;
  136. }
复制代码
最佳答案
2023-4-20 21:27:07

经过我重新审查代码,找到了问题所在。问题出在析构函数的调用顺序。首先,`Computer`的析构函数被调用,接着调用`Supplier`的析构函数。但是在`Supplier`的析构函数中,由于它继承了`CPU`、`VideoCard`和`Memory`类,所以它们的析构函数也会被调用。因此,在`Computer`的析构函数中,我们需要确保在删除`c0`、`v0`和`m0`之前调用它们的析构函数。

为了解决这个问题,我们可以在`Supplier`类中添加一个名为`cleanUp`的函数,该函数在`Computer`的析构函数中调用,确保调用`CPU`、`VideoCard`和`Memory`的析构函数。

在`Supplier`类中添加`cleanUp`函数:

  1. void cleanUp()
  2. {
  3.     cname.clear();
  4.     vname.clear();
  5.     mname.clear();
  6. }
复制代码


在`Computer`类的析构函数中调用`cleanUp`函数:

  1. ~Computer()
  2. {
  3.     if (c0 != NULL)
  4.     {
  5.         c0->cleanUp();
  6.         delete c0;
  7.         c0 = NULL;
  8.     }

  9.     if (v0 != NULL)
  10.     {
  11.         v0->cleanUp();
  12.         delete v0;
  13.         v0 = NULL;
  14.     }

  15.     if (m0 != NULL)
  16.     {
  17.         m0->cleanUp();
  18.         delete m0;
  19.         m0 = NULL;
  20.     }
  21. }
复制代码


现在,您的程序应该能够正常运行,不会报错。
Annotation 2023-04-20 223958.png

最佳答案

查看完整内容

经过我重新审查代码,找到了问题所在。问题出在析构函数的调用顺序。首先,`Computer`的析构函数被调用,接着调用`Supplier`的析构函数。但是在`Supplier`的析构函数中,由于它继承了`CPU`、`VideoCard`和`Memory`类,所以它们的析构函数也会被调用。因此,在`Computer`的析构函数中,我们需要确保在删除`c0`、`v0`和`m0`之前调用它们的析构函数。 为了解决这个问题,我们可以在`Supplier`类中添加一个名为`cleanUp`的函数, ...
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2023-4-20 21:27:07 | 显示全部楼层    本楼为最佳答案   

经过我重新审查代码,找到了问题所在。问题出在析构函数的调用顺序。首先,`Computer`的析构函数被调用,接着调用`Supplier`的析构函数。但是在`Supplier`的析构函数中,由于它继承了`CPU`、`VideoCard`和`Memory`类,所以它们的析构函数也会被调用。因此,在`Computer`的析构函数中,我们需要确保在删除`c0`、`v0`和`m0`之前调用它们的析构函数。

为了解决这个问题,我们可以在`Supplier`类中添加一个名为`cleanUp`的函数,该函数在`Computer`的析构函数中调用,确保调用`CPU`、`VideoCard`和`Memory`的析构函数。

在`Supplier`类中添加`cleanUp`函数:

  1. void cleanUp()
  2. {
  3.     cname.clear();
  4.     vname.clear();
  5.     mname.clear();
  6. }
复制代码


在`Computer`类的析构函数中调用`cleanUp`函数:

  1. ~Computer()
  2. {
  3.     if (c0 != NULL)
  4.     {
  5.         c0->cleanUp();
  6.         delete c0;
  7.         c0 = NULL;
  8.     }

  9.     if (v0 != NULL)
  10.     {
  11.         v0->cleanUp();
  12.         delete v0;
  13.         v0 = NULL;
  14.     }

  15.     if (m0 != NULL)
  16.     {
  17.         m0->cleanUp();
  18.         delete m0;
  19.         m0 = NULL;
  20.     }
  21. }
复制代码


现在,您的程序应该能够正常运行,不会报错。
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2023-4-20 22:05:03 | 显示全部楼层
根据您提供的代码,问题出在`Computer`类的构造函数中,您试图将已经构造的`Supplier`对象复制给`CPU`、`VideoCard`和`Memory`指针,这将导致析构时多次删除同一对象。为了解决这个问题,您可以将构造函数参数的类型改为指针,并在`main`函数中分配相应的对象。

首先,将`Computer`的构造函数参数类型更改为指针:

  1. class Computer
  2. {

  3.     CPU *c0;

  4.     VideoCard *v0;

  5.     Memory *m0;

  6. public:
  7.     Computer(Supplier *c, Supplier *v, Supplier *m)
  8.     {

  9.         c0 = c;

  10.         v0 = v;

  11.         m0 = m;

  12.         c0->cname = c->GetName();

  13.         v0->vname = v->GetName();

  14.         m0->mname = m->GetName();

  15.         cout << "This computer is assembled with " << c0->cname << " CPU, " << v0->vname

  16.              << " video card, " << m0->mname << " memory" << endl;
  17.     }

  18.     // ...其他成员函数不变
  19. };
复制代码


接下来,在`main`函数中分配相应的对象并传递指针:

  1. void fun0()
  2. {

  3.     Supplier *q0 = new Supplier("Qualcom");

  4.     Supplier *i0 = new Supplier;

  5.     i0->SetName("Intel");

  6.     Supplier *a0 = new Supplier("AMD");

  7.     Computer c0(q0, i0, a0);

  8.     c0.work();
  9. }

  10. int main()
  11. {

  12.     fun0();

  13.     system("pause");

  14.     return 1;
  15. }
复制代码


最后,您需要更新`Computer`类的析构函数,以删除这些动态分配的`Supplier`对象。

  1. ~Computer()
  2. {

  3.     if (c0 != NULL)
  4.     {
  5.         delete c0;

  6.         c0 = NULL;
  7.     }

  8.     if (v0 != NULL)
  9.     {
  10.         delete v0;

  11.         v0 = NULL;
  12.     }

  13.     if (m0 != NULL)
  14.     {

  15.         delete m0;

  16.         m0 = NULL;
  17.     }
  18. }
复制代码


这样修改后,您的程序应该不会再报错,并按预期运行。
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2023-4-20 22:31:30 | 显示全部楼层
isdkz 发表于 2023-4-20 22:05
根据您提供的代码,问题出在`Computer`类的构造函数中,您试图将已经构造的`Supplier`对象复制给`CPU`、`Vi ...

改了之后还是不行
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2023-4-20 22:32:02 | 显示全部楼层
本帖最后由 Eden00 于 2023-4-20 22:44 编辑
isdkz 发表于 2023-4-20 22:05
根据您提供的代码,问题出在`Computer`类的构造函数中,您试图将已经构造的`Supplier`对象复制给`CPU`、`Vi ...

  1. #include <iostream>

  2. #include <string>

  3. #include <cmath>

  4. #include <stdlib.h>

  5. #include <ctime>

  6. using namespace std;

  7. class CPU
  8. {

  9. public:
  10.     string cname;

  11.     virtual void calculate() = 0;
  12.     ~CPU()
  13.     {
  14.         cout << cname << " CPU is destructed" << endl;
  15.     }
  16. };

  17. class VideoCard
  18. {

  19. public:
  20.     string vname;

  21.     virtual void display() = 0;
  22.     ~VideoCard()
  23.     {
  24.         cout << vname << " video card is destructed" << endl;
  25.     }
  26. };

  27. class Memory
  28. {

  29. public:
  30.     string mname;

  31.     virtual void store() = 0;
  32.     ~Memory()
  33.     {
  34.         cout << mname << " memory is destructed" << endl;
  35.     }
  36. };

  37. class Supplier : public CPU, public VideoCard, public Memory
  38. {

  39.     string name;

  40.     void calculate()
  41.     {

  42.         cout << name << " CPU is calculating" << endl;
  43.     }

  44.     void store()
  45.     {

  46.         cout << name << " memory is stoing" << endl;
  47.     }

  48.     void display()
  49.     {

  50.         cout << name << " video card is displaying" << endl;
  51.     }

  52. public:
  53.     Supplier()
  54.     {

  55.         cout << "Supplier is structed without argument" << endl;
  56.     }

  57.     Supplier(string n) : name(n)
  58.     {

  59.         cout << "Supplier is structed with name as " << n << endl;
  60.     }

  61.     string SetName(string n)
  62.     {

  63.         cout << "Supplier name is set by Class Supplier as " << n << endl;

  64.         name = n;

  65.         return name;
  66.     }

  67.     string GetName()
  68.     {

  69.         return name;
  70.     }

  71.     ~Supplier()
  72.     {

  73.         cout << name << " supplier is destructed" << endl;
  74.     }
  75. };

  76. class Computer
  77. {

  78.     CPU *c0;

  79.     VideoCard *v0;

  80.     Memory *m0;

  81. public:
  82.     Computer(Supplier *c, Supplier *v, Supplier *m)
  83.     {

  84.         c0 = c;

  85.         v0 = v;

  86.         m0 = m;

  87.         c0->cname = c->GetName();

  88.         v0->vname = v->GetName();

  89.         m0->mname = m->GetName();

  90.         cout << "This computer is assembled with " << c0->cname << " CPU, " << v0->vname

  91.              << " video card, " << m0->mname << " memory" << endl;
  92.     }

  93.     ~Computer()
  94.     {

  95.        if (c0 != NULL)
  96.         {
  97.             cout << c0->cname << endl
  98.                  << c0 << endl;
  99.             delete c0;

  100.             c0 = NULL;
  101.         }

  102.         if (v0 != NULL)
  103.         {
  104.             cout << v0->vname << endl
  105.                  << v0 << endl;
  106.             delete v0;

  107.             v0 = NULL;
  108.         }

  109.         if (m0 != NULL)
  110.         {

  111.             delete m0;

  112.             m0 = NULL;
  113.         }
  114.     }

  115.     void work()
  116.     {

  117.         c0->calculate();

  118.         v0->display();

  119.         m0->store();
  120.     }
  121. };

  122. void fun0()
  123. {

  124.     Supplier *q0=new Supplier("Qualcom");

  125.     Supplier *i0=new Supplier("Intel");


  126.     Supplier *a0=new Supplier("AMD");

  127.     Computer c0(q0, i0, a0);

  128.     c0.work();
  129. }

  130. int main()
  131. {

  132.     fun0();

  133.     system("pause");

  134.     return 1;
  135. }
复制代码

小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2023-4-21 10:02:27 | 显示全部楼层
isdkz 发表于 2023-4-20 23:38
经过我重新审查代码,找到了问题所在。问题出在析构函数的调用顺序。首先,`Computer`的析构函数被调用, ...

c0是CPU指针,v0是videocard指针按照定义应该不能调用supplier类的函数。
但是思路是对的,应该要确保supplier析构时,父类们也一起析构,因此感谢啦
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-6-10 15:32

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表