0

I'm using visual studio.

I have 3 class. It's ok when I try to print Rectangle ABCD, but when i push ABCD into Array [rectangle] A and try to print ABCD again, the "wntdll.pdb not loaded" appear and i continue, it's "triggers breakpoint error!!" at delete in ~Rectangle()

I know it's something up to the pointer in class Rectangle but can't firgure out.

`int main(){
    Array<Rectangle>A;
    Rectangle a;
    cout << a;     //It's oke
    A.PushBack(a); // problem here
    cout<<a;
}`
    class Point
    {
    private:
       float _x;
       float _y;
    public:
       float GetX() { return _x; }
       float GetY() { return _y; }
    public:
       Point();
       Point(float, float);
       Point(const Point&);
       ~Point() {};
    public:
       string ToString() const;
    public:
       friend istream& operator>>(istream&, Point*);
       friend ostream& operator<<(ostream&, const Point&);
    };
    Point::Point() {
       _x = 1;
       _y = 1;
    }
    Point::Point(float x, float y) {
       _x = x;
       _y = y; 
    }
    Point::Point(const Point& a) {
       _x = a._x;
       _y = a._y;
    }
    string Point::ToString() const{
       stringstream out;
       out << "( " << _x << "," << _y << " )";
       return out.str();
    }
    istream& operator>>(istream& in, Point* a) {
       cout << "Nhap x: ";
       in >> a->_x;
       cout << "Nhap y: ";
       in >> a->_y;
       return in;
    }
    ostream& operator<<(ostream& out, const Point& a)
    {
       out << a.ToString();
       return out;
    }
    ```


class Rectangle
{
private:
    Point* _topleft;
    Point* _botright;
public:
    void Set_topleft(Point tl) { _topleft = &tl; }
    Point Get_topleft() { return *_topleft; }
    void Set_botright(Point br) { _botright = &br; }
    Point Get_botright() { return *_botright; }
public:
    Rectangle();
    Rectangle(Point*, Point*);
    ~Rectangle();
public:
    string ToString() const;
public:
    friend istream& operator>>(istream&, Rectangle&);
    friend ostream& operator<<(ostream&, const Rectangle&);
};
Rectangle::Rectangle()
{
    _topleft = new Point(0, 2);
    _botright = new Point(3, 0);
}
Rectangle::Rectangle(Point* a, Point* b)
{
    _topleft = new Point(*a);
    _botright = new Point(*b);
}
Rectangle::~Rectangle()
{
    delete _topleft;
    delete _botright;
}
string Rectangle::ToString() const
{
    stringstream out;
    out << "A" << *_topleft << "+" << "D" << *_botright;
    return out.str();
}
istream& operator>>(istream& in, Rectangle& a)
{
    std::cout << "A( x,y ): ";
    in >> a._topleft;
    std::cout << "D( x,y ): ";
    in >> a._botright;
    return in;
}
ostream& operator<<(ostream& out, const Rectangle& a)
{
    out << a.ToString();
    return out;
}
```
    template<class T>
    class Array
    {
    private:
        T* _a;
        int _len;
    public:
        Array();
        ~Array();
    public:
        int length() { return _len; }
        void PushBack(T);
        T GetAt(int);
    };
    template<class T>
    Array<T>::Array() {
        _a = new T[128];
        _len = 0;
    }
    template<class T>
    Array<T>::~Array() {
        delete[] _a;
        _len = 0;
    }
    template<class T>
    void Array<T>::PushBack(T value) {
        if (_len >= 128)
        {
            std::cout << "Array is over size, which is 128\n";
            return;
        }
        _a[_len] = value;
        _len++;
    }
    template<class T>
    T Array<T>::GetAt(int pos) {
        return _a[pos];
    }

    ```



I'mMotivated
  • 175
  • 1
  • 1
  • 8
  • 2
    `Point* _topleft; Point* _botright;` -- Why are these pointers? You could have simply done `Point _topleft; Point_botright;` and spared yourself all of the trouble you're having. It even makes more sense to do the latter, since it conveys exactly what those members are: `Point`'s. – PaulMcKenzie Nov 05 '19 at 14:26
  • @PaulMcKenzie It's the simples and the best solution :) – Raffallo Nov 05 '19 at 14:28
  • It's an task my teacher gave us. Sure everything is fine without these pointers . – I'mMotivated Nov 05 '19 at 14:29
  • 1
    `istream& operator>>(istream& in, Point* a)` -- This should be: `istream& operator>>(istream& in, Point& a);` -- The second parameter shouldn't be a pointer, instead it should be a reference. – PaulMcKenzie Nov 05 '19 at 14:40
  • I thought those constructor is necessary (copy, init, des)? – I'mMotivated Nov 05 '19 at 14:47
  • @I'mMotivated -- For the `Point` class, they are not necessary. For that `Rectangle` class, since you introduced pointer members to it, plus the dynamic allocation, requires copy constructor *and* assignment operator, plus destructor. – PaulMcKenzie Nov 05 '19 at 15:03
  • Ah! Knew it! But it's a task therefore i have to follow my teacher requirements haha – I'mMotivated Nov 05 '19 at 15:06

1 Answers1

2

The problem in your code is that when you PushBack the Rectangle object a into the array, you create copy of this object. This means that you just copy pointers _topleft and _botright. So in this part of code, you have 2 objects with the same pointers, so you're trying to delete twice the same part of memory. To fix this you need to define own copy constructor, which will create new pointers in the new object.
Remember also to define own move constructors or make it disable for your class.

Rectangle(const Rectangle &other) 
 {
        if(other._topleft)
           _topleft= new Point(*other._topleft); 
        else
            _topleft = nullptr;
        if(other._botright)
           _botright= new Point(*other._botright); 
        else
            _topleft = nullptr;
 } 

The next problem is because of definition of void Array<T>::PushBack(T value). Please change it to the void Array<T>::PushBack(const T& value). Also, try Rectangle(Rectangle&& o) = delete;

Raffallo
  • 651
  • 8
  • 19
  • Hmm I thought about this too! Added your code but not fixed yet. I aslo think it's because " = " in my PushBack and overloaded an "=" like your method but it dont work. – I'mMotivated Nov 05 '19 at 14:19
  • it works like a charm! ty a lot. Must keep in mind always have 3 init, copy, des :) – I'mMotivated Nov 05 '19 at 14:49
  • 1
    Those are not the 3 function that make up the [rule of 3](https://stackoverflow.com/questions/4172722/what-is-the-rule-of-three). it is copy constructor, assignment operator, and destructor. You didn't implement an assignment operator, thus `Rectangle r1; Rectangle r2;...r1 = r2;` will not work properly. – PaulMcKenzie Nov 05 '19 at 15:04