Domanda

This code works appropriately if I don't use and then delete a pointer for the base class Output. The destructor for Output is called and seems to work appropriately. Am I missing something here?

// 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;
}
È stato utile?

Soluzione

There are several major issues with this code:

First, you should not use multiple inheritance for this. It is completely unnecessary and will lead to very difficult to track down bugs.

Second, you do not need to test for nullptr before deleting a pointer - it is redundant as delete already does that.

Third, neither of your base classes has a virtual destructor. (your current error)

Forth, you are violating the Rule of 3 in your Output class (and likely will need to use it in all of them).

Fifth, assuming string means std::string. There is no reason for it to be a string* - just use std::string and avoid having to allocate and deallocate it.

I didn't fix your design issues, but your memory access and polymorphic issues are fixed 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;
}

EDIT: An example of a better way to implement the desired program can be found here.

Altri suggerimenti

Your Output and Polygon class destructors should be virtual also:

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

  public:
        // ...

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

Also note: Instead of using a std::string* pointer, you can simply use a std::string myString; member:

  private:
    std::string myString;

and leave behind bothering around with getting new string() and delete myString; right for any cases.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top