重载<<运算符返回错误的值(C ++)

时间:2016-02-15 22:10:54

标签: c++ c++11

我是C ++的初学者,最近我的小程序遇到了一个非常令人沮丧的问题,我正在练习运算符重载和模板。

我创建了一个名为SortedVector的模板类,可以存储各种类型的实例。

using namespace std;

template <class T, int size> class SortedVector {
public:
    SortedVector();
    bool add(const T& v);
    T& median();
    void sortArray();
    void removeLarge(const T& v);
    void print(ostream &os);
    void compexch(T& x, T& y);
    void sortArray(T* data, int s);

private:
    T arr[size];
    int arraySize;
};

template <class T, int size> SortedVector<T, size>::SortedVector() {


    arraySize = 0;

    for (int i = 0; i < size; i++) {
        arr[i] = T();
    }
}

template <class T, int size> bool SortedVector<T, size>::add(const T& v) {

    if (arraySize > size - 1) {
        cout << "Array is full!" << endl;
        return false;
    } else {

        arr[arraySize] = v;
        arraySize++;

        sortArray(arr, arraySize);
    }

    return true;
}

template <class T, int size> void SortedVector<T, size>::sortArray(T* data, int s) {
    for (int i = 0; i < s - 1; i++) {
        for (int j = i + 1; j < s; j++) {
            compexch(data[i], data[j]);
        }
    }
}

template <class T, int size > T & SortedVector<T, size>::median() {

}

template <class T, int size> void SortedVector<T, size>::removeLarge(const T & v) {

}

template <class T, int size> void SortedVector<T, size>::print(ostream & os) {


    for (int i = 0; i < arraySize; i++) {
        cout << arr[i] << endl;
    }
}

template <class T, int size> inline void SortedVector<T, size>::compexch(T& x, T& y) {
    if (y < x) {
        T temp = x;
        x = y;
        y = temp;
    }
}

它可以成功存储整数,也可以存储多边形(在早期作业中创建的自定义类)。

Polygon.h:

class Polygon {
public:

    Polygon(Vertex vertexArray[], int size);
    Polygon() : vertices(0), arraySize(0) {}
    ~Polygon() {delete[] vertices;}
    void add(Vertex v);
    float area();
    int minx();
    int maxx();
    int miny();
    int maxy();
    int numVertices() const {return arraySize;}
    friend ostream &operator << (ostream &output, const Polygon& polygon);
    friend bool operator > (Polygon polygon1, Polygon polygon2);
    friend bool operator < (Polygon polygon1, Polygon polygon2);

private:

    int arraySize;
    Vertex * vertices;

};

Polygon.cpp声明:

using namespace std;

void Polygon::add(Vertex v) {
    arraySize++;
    Vertex * tempVertexes = new Vertex[arraySize];
    for (int i = 0; i < arraySize; i++) {
        if (i == arraySize - 1) {
            tempVertexes[i] = v;
        } else {
            tempVertexes[i] = vertices[i];
        }
    }
    delete [] vertices;
    vertices = tempVertexes;

}

Polygon::Polygon(Vertex vertexArray[], int size) {
    arraySize = size;
    vertices = new Vertex[size];

    for (int i = 0; i < size; i++) {
        vertices[i] = vertexArray[i];
    }
}

float Polygon::area() {
    float area = 0.0f;

    for (int i = 0; i < arraySize - 1; ++i) {
        area += (vertices[i].getXposition() * vertices[i + 1].getYposition()) - (vertices[i + 1].getXposition() * vertices[i].getYposition());
    }

    area += (vertices[0].getYposition() * vertices[arraySize - 1].getXposition()) - (vertices[arraySize - 1].getYposition() * vertices[0].getXposition());

    area = abs(area) *0.5;

    return area;
}



ostream& operator<<(ostream &output, const Polygon& polygon) { //Kolla denna!


    output << "{";
    for (int i = 0; i < polygon.numVertices(); i++) {
        output << "(" << polygon.vertices[i].getXposition() << "," << polygon.vertices[i].getYposition() << ")";

    }
    output << "}";

    return output;

}

bool operator>(Polygon polygon1, Polygon polygon2) {
    if (polygon1.area() > polygon2.area()) {
        return true;
    } else {
        return false;
    }
}

bool operator<(Polygon polygon1, Polygon polygon2) {
    if (polygon1.area() < polygon2.area()) {
        return true;
    } else {
        return false;
    }
}


template <class T> inline void compexch(T& x, T& y) {
    if (y < x) {
        T temp = x;
        x = y;
        y = temp;
    }
}

Vertex类的代码:

class Vertex {
public:
    Vertex() : y(0), x(0) {}
    Vertex(int xPosition, int yPosition) : x(xPosition), y(yPosition) {}
    ~Vertex() {}
    int getXposition() const {return x;}
    int getYposition() const {return y;}

private:
    int x;
    int y;


};

然而问题是重载的&lt;&lt; -operator似乎从main方法打印出错误的值:

int main() {

    SortedVector<Polygon, 10> polygons;
    SortedVector<int, 6> ints;

    ints.add(3);
    ints.add(1);
    ints.add(6);

    Vertex varr[10];
    varr[0] = Vertex(0, 0);
    varr[1] = Vertex(10, 0);
    varr[2] = Vertex(5, 2);
    varr[3] = Vertex(5, 5);
    polygons.add(Polygon(varr, 4));
    cout << "varr area:" << (Polygon(varr, 4)).area() << endl;

    varr[0] = Vertex(0, 0);
    varr[1] = Vertex(25, 8);
    varr[2] = Vertex(10, 23);
    polygons.add(Polygon(varr, 3));
    cout << "var area (1):" << (Polygon(varr, 3)).area() << endl;
    varr[0] = Vertex(0, 0);
    varr[1] = Vertex(5, 0);
    varr[2] = Vertex(5, 3);
    varr[3] = Vertex(4, 8);
    varr[4] = Vertex(2, 10);
    polygons.add(Polygon(varr, 5));
    cout << "var area (2):" << (Polygon(varr, 5)).area() << endl;
    polygons.print(cout);
    ints.print(cout);

    cout << "MEDIAN: " << ints.median() << endl;
    cout << "MEDIAN: " << polygons.median() << endl;

    return 0;

}

打印的代码是:

var area (1):247.5
var area (2):33.5
{(6029504,0)(5,0)(5,3)}
{(6029504,0)(5,0)(5,3)(4,8)}
{(6029504,0)(5,0)(5,3)(4,8)(2,10)}
1
3
6
MEDIAN: 1
MEDIAN: {(6029504,0)(5,0)(5,3)}

首先,该方法打印出相同的多边形但具有不同的大小。其次,它指出了数组中第一个对象的错误getXPosition()。其他所有(实现,如整数和区域)是正确的。为什么是这样?我在这里错过了一些重要的事情,还是我完全不喜欢我的课程?

如果需要更多代码,我很乐意提供。

此致

1 个答案:

答案 0 :(得分:3)

鉴于您发布的代码,问题很清楚是什么问题。

你在这里按价值传递Polygon

friend bool operator > (Polygon polygon1, Polygon polygon2);
friend bool operator < (Polygon polygon1, Polygon polygon2);

您正在复制和分配值:compexch

if (y < x) {
    T temp = x;  // copy constructor
    x = y;  // assignment
    y = temp;  // assigment
}

这意味着将进行复制,并且无法安全地复制您的Polygon类。调用其中任何一个函数时,您将遇到内存泄漏和错误。

您应该实现适当的复制构造函数和赋值运算符,其签名为:

Polygon(const Polygon& rhs);  // copy constructor
Polygon& operator=(const Polygon& rhs); // assignment operator

应该实现这两个功能。有关此信息,请参阅the Rule of 3

但是,对于operator <operator >,您应该将引用而不是值传递给这些函数:

friend bool operator > (Polygon& polygon1, Polygon& polygon2);
friend bool operator < (Polygon& polygon1, Polygon& polygon2);

然后复制构造函数和赋值运算符不起作用,因为参数类型是引用。

为了完整性,让我们尝试实现复制/赋值功能:

例如,复制构造函数可以像这样实现:

Polygon::Polygon(const Polygon& rhs) : vertices(new int[rhs.arraySize]), 
                                       arraySize(rhs.arraySize)
{
   for (int i = 0; i < arraySize; ++i)
      vertices[i] = rhs.vertices[i];
}

然后对于赋值运算符,使用copy / swap idiom

Polygon& operator=(const Polygon& rhs)
{
    Polygon temp(rhs);
    std::swap(temp.arraySize, arraySize);
    std::swap(temp.vertices, vertices);
    return *this;
}

一旦实现了这些函数,再加上调用delete[]的析构函数,您就不再需要复制对象了。

其他问题:

此外,您最初应该只重载<==,最初使用“完整”实现,并针对这两个运算符编写其他关系运算符。

现在,你犯了一个经典错误:编写一个运算符(operator >),然后在实现operator <时尝试将逻辑“由内向外”。如果operator >的逻辑更复杂,并且自己的工作需要弄清楚“与&lt;”相反的是什么呢?

如果您实施了==,那么运营商>就会变为:

return !(polygon1 < polygon2) && !(polygon == polygon2);  // <-- this can be further improved by implementing operator !=