为什么这个删除导致核心转储?

时间:2014-02-21 21:15:46

标签: c++ multiple-inheritance

如果我不使用然后删除基类Output的指针,则此代码可以正常工作。调用Output的析构函数,似乎正常工作。我在这里错过了什么吗?

// multiple inheritance
// Testing overload of muliple inheritance of pure virtual functions.

#include <iostream>
#include <string>

using namespace std;

class Polygon {
  protected:
    int width, height;
  public:
    Polygon (int a, int b) : width(a), height(b) {}
    ~Polygon() = default;
    virtual int area() = 0;
};

class Output {
  private:
    string* myString;

  public:
    Output() {
      myString = nullptr;
    }

    Output(const string& s) {
      myString = new string(s);
    }

    // This seems to work, but ther core dump happens right afterwards.
    ~Output() {
      cout << "delete called with: " << myString << '\n';
      if (myString != nullptr)
        delete myString;
    }
    virtual int area() = 0;
    void print () {
      cout << *myString << this->area() << '\n';
    }
};



class Rectangle: public Polygon, public Output {
  public:
    Rectangle (int a, int b) : Polygon(a,b), Output{"A Rectangle's area is: "} {}
    int area () {
     return width*height;
   }
};

class Triangle: public Polygon, public Output  {
  public:
    Triangle (int a, int b) : Polygon{a,b}, Output{"A Triangle's area is: "} {}
    int area ()
      { return width*height/2; }
};

int main () {
  Output * ptr1 = new Rectangle(4,5);
  Output * ptr2 = new Triangle(4,5);

  ptr1->print();
  ptr2->print();

  // Causes core dump.  
  delete ptr1;
  delete ptr2;

  return 0;
}

2 个答案:

答案 0 :(得分:3)

此代码存在几个主要问题:

首先,您不应该为此使用多重继承。这完全是不必要的,并且将导致很难追踪错误。

其次,在删除指针之前,您不需要测试nullptr - 它是多余的,因为delete已经这样做了。

第三,你的基类都没有虚拟析构函数。 (您当前的错误)

第四,你违反了Output课程中的Rule of 3(可能需要在所有课程中使用它)。

第五,假设string表示std::string。它没有理由成为string* - 只需使用std::string并避免分配和取消分配它。

我没有修复您的设计问题,但您的内存访问和多态问题已修复here

#include <iostream>
#include <string>

using namespace std;

class Polygon 
{
  protected:
    int width, height;
  public:
    Polygon (int a, int b) : width(a), height(b) {}
    virtual ~Polygon() { } // needed!
    virtual int area() = 0;
};

class Output 
{
  private:
    std::string myString; // no need to be a pointer

  public:
    Output() {    }

    Output(const string& s) : myString(s) {   }

    virtual ~Output() {    } // also needed!
    virtual int area() = 0;
    void print () {
      cout << myString << this->area() << '\n';
    }
};



class Rectangle: public Polygon, public Output 
{
  public:
    Rectangle (int a, int b) : Polygon(a,b), Output{"A Rectangle's area is: "} {}
    int area () {
     return width*height;
   }
};

class Triangle: public Polygon, public Output  
{
  public:
    Triangle (int a, int b) : Polygon{a,b}, Output{"A Triangle's area is: "} {}
    int area ()
      { return width*height/2; }
};

int main () 
{
  Output * ptr1 = new Rectangle(4,5);
  Output * ptr2 = new Triangle(4,5);

  ptr1->print();
  ptr2->print();

  // Causes core dump.  
  delete ptr1;
  delete ptr2;

  return 0;
}

编辑:可以找到实现所需程序的更好方法的示例here

答案 1 :(得分:2)

您的OutputPolygon类析构函数也应为virtual

class Output {
  private:
    std::string* myString;

  public:
        // ...

    virtual ~Output() { 
 // ^^^^^^^
    }
};

另请注意:您可以简单地使用std::string*成员,而不是使用std::string myString;指针:

  private:
    std::string myString;

并且在任何情况下都可以使new string()delete myString;正确无误。