C++ 毁灭者无法解释的行为

C++ 毁灭者无法解释的行为,c++,destructor,C++,Destructor,在这个问题上: 最上面的答案有以下注释: Note that the destructor of the base class will be called implicitly after the destructor of the derived class finishes. This is a difference to the usual virtual functions. 我制作了一个快速的示例程序来测试这一点 class A { public: virtual ~A() {

在这个问题上:

最上面的答案有以下注释:

Note that the destructor of the base class will be called implicitly after the destructor of the derived class finishes. This is a difference to the usual virtual functions.
我制作了一个快速的示例程序来测试这一点

class A {
public:
  virtual ~A() {
    std::cout << "A DESTRUCTOR" << std::endl;
  }
};
class B {
public:
  virtual ~B() {
    std::cout << "B DESTRUCTOR" << std::endl;
  }
};
class C {
public:
  virtual ~C() {
    std::cout << "C DESTRUCTOR" << std::endl;
  }
};

int main(int argc, char** argv)
{
  A * aPtr = (A *)new C();
  C * cPtr = new C();

  delete aPtr;
  delete cPtr;
  return 0;
}
这似乎与注释不符

我的问题是,如何在需要运行多个析构函数的类层次结构中安全地实现析构函数

例如,假设类A和类C都在堆上分配了一个属性,并且需要清理它们。我如何安全地编写这样的层次结构?注意:我目前没有尝试编写这样的层次结构,请不要回答“不要,这是糟糕的设计”。另外,我知道智能指针可以解决这个问题,这更多是为了确保我了解底层机制

它是否要求C类正确清理A类属性?如果该财产是私有的,而不是受保护的或公共的,会发生什么?我是否错过了什么,或者误解了我所看到的

用于运行这些测试的编译器

gcc (Ubuntu 4.8.4-2ubuntu1~14.04) 4.8.4
  • 您忘记了类之间的继承

  • 这将在执行
    delete
    行时触发

    A * aPtr = (A *)new C();
    
  • 我相信这就是你一直在寻找的

    class A {
    public:
      virtual ~A() {
        std::cout << "A DESTRUCTOR" << std::endl;
      }
    };
    class B : public A{
    public:
      virtual ~B() {
        std::cout << "B DESTRUCTOR" << std::endl;
      }
    };
    class C : public B{
    public:
      virtual ~C() {
        std::cout << "C DESTRUCTOR" << std::endl;
      }
    };
    
    int main(int argc, char** argv)
    {
      A * aPtr = new C(); // The cast here is not needed
      C * cPtr = new C();
    
      delete aPtr;
      delete cPtr;
      return 0;
    }
    
  • 您忘记了类之间的继承

  • 这将在执行
    delete
    行时触发

    A * aPtr = (A *)new C();
    
  • 我相信这就是你一直在寻找的

    class A {
    public:
      virtual ~A() {
        std::cout << "A DESTRUCTOR" << std::endl;
      }
    };
    class B : public A{
    public:
      virtual ~B() {
        std::cout << "B DESTRUCTOR" << std::endl;
      }
    };
    class C : public B{
    public:
      virtual ~C() {
        std::cout << "C DESTRUCTOR" << std::endl;
      }
    };
    
    int main(int argc, char** argv)
    {
      A * aPtr = new C(); // The cast here is not needed
      C * cPtr = new C();
    
      delete aPtr;
      delete cPtr;
      return 0;
    }
    
    改为:

    class A {
    public:
      virtual ~A() {
        std::cout << "A DESTRUCTOR" << std::endl;
      }
    };
    class B : public A{
    public:
      virtual ~B() {
        std::cout << "B DESTRUCTOR" << std::endl;
      }
    };
    class C : public B{
    public:
      virtual ~C() {
        std::cout << "C DESTRUCTOR" << std::endl;
      }
    
    A类{
    公众:
    虚拟~A(){
    std::cout更改为:

    class A {
    public:
      virtual ~A() {
        std::cout << "A DESTRUCTOR" << std::endl;
      }
    };
    class B : public A{
    public:
      virtual ~B() {
        std::cout << "B DESTRUCTOR" << std::endl;
      }
    };
    class C : public B{
    public:
      virtual ~C() {
        std::cout << "C DESTRUCTOR" << std::endl;
      }
    
    A类{
    公众:
    虚拟~A(){
    
    std::cout您在这里所指的行为是派生类中的虚拟析构函数的行为,即继承其他类的类


    还记得使用C++来编译C++。

    这里所指的行为是派生类中虚析构函数的行为,意思是继承其他类的类。


    还记得使用C++来编译C++。

    正如其他人所注意到的,你希望(需要,真的)使用继承。< /P> 他们没有注意到的是,编译器只允许你这样做,因为你在一个不应该使用的地方使用了强制转换。如果你需要使用强制转换,你真的应该坐下来,仔细考虑为什么强制转换是必要的,并且确保它所做的事情是你真正想要做的

    如果没有强制转换,编译器将阻止编译损坏的代码。更正继承后,没有强制转换也可以:

    #include <iostream>
    
    class A {
    public:
      virtual ~A() {
        std::cout << "A DESTRUCTOR" << std::endl;
      }
    };
    class B : public A {
    public:
      virtual ~B() {
        std::cout << "B DESTRUCTOR" << std::endl;
      }
    };
    class C : public B {
    public:
      virtual ~C() {
        std::cout << "C DESTRUCTOR" << std::endl;
      }
    };
    
    int main(int argc, char** argv) {
      A * aPtr = new C();
    
      delete aPtr;
    }
    

    正如其他人所指出的,您希望(实际上需要)在这里使用继承

    他们没有注意到的是,编译器只允许你这样做,因为你在一个不应该使用的地方使用了强制转换。如果你需要使用强制转换,你真的应该坐下来,仔细考虑为什么强制转换是必要的,并且确保它所做的事情是你真正想要做的

    如果没有强制转换,编译器将阻止编译损坏的代码。更正继承后,没有强制转换也可以:

    #include <iostream>
    
    class A {
    public:
      virtual ~A() {
        std::cout << "A DESTRUCTOR" << std::endl;
      }
    };
    class B : public A {
    public:
      virtual ~B() {
        std::cout << "B DESTRUCTOR" << std::endl;
      }
    };
    class C : public B {
    public:
      virtual ~C() {
        std::cout << "C DESTRUCTOR" << std::endl;
      }
    };
    
    int main(int argc, char** argv) {
      A * aPtr = new C();
    
      delete aPtr;
    }
    

    你忘了让你的类彼此派生!继承在哪里?大多数情况下,程序执行的是你键入的内容,而不是你想要的内容!C不是从A派生的,因此,你的类型是
    david\u hero\u cast(pc)
    你忘了让你的类彼此派生!继承在哪里?大多数情况下,程序执行你键入的内容,而不是你想要的内容!C不是从A派生的,因此,你的演员阵容是某种类型的
    david\u hero\u cast(pc)我想,我不知道我是怎么错过的,我做的事情太多了。我会尽快标记为接受。强制转换可能是危险的,派生的pTrto to > BaseTPTR强制转换是允许的,因为C++的语言没有继承任何继承,但其他转换需要明确的动作。(和你的情况一样)我想说,我不知道我是怎么错过的。我想,做一件事情太多了。我会尽快地接受。投的可能是危险的,派生的pTrto to > BaseTPTR铸件是允许的C++语言,没有任何明确的铸造,因为继承它们,但其他转换需要明确的行动。(就像你的情况一样)你是对的,我只是突然来到控制台输入完整性信息,没有太多考虑:)你是对的,我只是突然来到控制台输入完整性信息,没有太多考虑:)虽然这解决了问题,但没有解释为什么。是什么让你认为
    C
    应该从
    B
    继承而不是直接从
    A
    继承?虽然这解决了问题,但没有解释为什么。是什么让你认为
    C
    应该从
    B
    继承而不是直接从
    A
    继承?从技术上讲,这是一个问题e cast很好(这是一个
    重新解释\u cast
    ),删除不是。这就是为什么我在执行删除行时写了“它将触发”。虽然可能不清楚,但我会在中编辑它,感谢技术上,该cast很好(这是
    重新解释\u cast
    ),删除不是。这就是我写“它将触发”的原因,一旦删除行被执行。但可能不清楚,我将在中编辑此内容,谢谢