带有类的C ++重载操作符

时间:2015-10-17 20:58:02

标签: c++ class operators

对于这个程序,我想创建一个SET类,它包含一组数字正数且没有重复数。在我创建了SET类之后,我为+和*创建了重载运算符,将两个集合在一起,并分别找到两个集合的交叉数。然而,在我开始测试代码之后,我注意到+和*重载的运算符不能在包含数字的两个集合上工作,除非我创建了一个新的SET来输出数据。例如,我必须这样做:

SET set3 = set1 + set2;
cout << set3;

而不是只做:

cout << set1 + set2;

只有当两个集合都为空或者1个集合已填满且另一个集合为空时,我才能输出上述代码。我不确定我做错了什么,所以无法输出两个填充集。我将代码分成三个文件。 这是头文件:

//CSCI 205
//Brett Milinski
//Assignment 2 - The Set Class
//This problem wants us to create a set class to hold a mathematical set of    integers and can later be manipulated to implement the Sieve of Eratosthenes method for computing prime numbers

    #ifndef SET_H
    #define SET_H
    #include<iostream>
    using namespace std;

    class SET
    {
    private: int a[50];
             int length;
             const int SIZE = 50;

    public: SET();
            SET(int a, int b);
            void print(ostream &os);
            void insert(int x);
            void erase(int x);
            int searchList(int a[], int length, int x);
            int addSearchList(int a[], int length, int x);
            friend SET& operator+(SET& a, SET& b);
            friend SET& operator*(SET& a, SET& b);
            friend ostream& operator<<(ostream& os, SET& a);
            SET& sieveOfEratosthenes(int n);
    };
    #endif

这是定义方法的set.cpp文件:

//CSCI 205
//Brett Milinski
//Assignment 2 - The Set Class
//This problem wants us to create a set class to hold a mathematical set of integers and can later be manipulated to implement the Sieve of Eratosthenes method for computing prime numbers

#include"set.h"
#include<iostream>
using namespace std;

SET::SET() //default constructor
{
    length = 0;
}

SET::SET(int start, int end) //overloaded constructor
{
    length = end - start + 1; //end of range of numbers to be input

    if (length <= SIZE) //range isn't too big for the array
    {
        for (int x = 0; x < length; x++)
        {
            a[x] = start;
            start++;
        }
    }
}

void SET::insert(int x) //function to insert numbers from the array
{
    bool inserted = false;

    for (int i = 0; i < length; i++) //check to see if the value is already in the set, if so, don't add
    {
        if (a[i] == x)
        {
            inserted = true;
            cout << "Sorry, the SET already contains that number." << endl;
        }
    }

    if (inserted == false) //the SET does not contain the number that is trying to be inserted
    {
        int check = addSearchList(a, length, x); //check the position of where to add the value

        if (length == SIZE) //check to see if the array is already full
        {
            cout << "You cannot add anymore elements to this array because it is full." << endl;
        }
        else if (check == length) //check to see if it is added at the end
        {
            length++; //make the array one size bigger to make room for the addition
            a[length - 1] = x; //add the value to the end
        }
        else
        {
            length++; //make the array one size bigger to make room for the addition
            for (int i = length - 1; i >= check; i--) //start at the bottom and move up towards where the new value should be
            {
                a[i] = a[i - 1]; //ripple down
            }
            a[check] = x; //add in the new value
        }
    }

}

void SET::erase(int x) //function to erase numbers from the array
{
    int check = searchList(a, length, x); //check to see what the position is

    if (length == 0) //check to see if the array is empty before deleting anything
    {
        cout << "The array is empty and therefore nothing can be deleted from the elements." << endl;
    }
    else if (check != -1) //check to see if the value is found
    {
        for (int x = check; x < length - 1; x++)
        {
            a[x] = a[x + 1]; //ripples every element up
        }
        length--; //makes the array one size smaller to accomadate the deletion
    }
    else
    {
        cout << "The value entered is not in the array." << endl; //the value being checked for does not exist
    }

}

void SET::print(ostream &os) //function to output the values of the array
{
    os << "The contents of the set are:" << endl;
    for (int x = 0; x < length; x++)
    {
        os << a[x] << " ";
    }
    os << endl;
}

int SET::searchList(int a[], int length, int x) //a search for the erase function
{
    int index = 0;               // Used as a subscript to search array 
    int position = -1;           // Used to record position of search value 
    bool found = false;          // Flag to indicate if the value was found 

    while (index < length && a[index] <= x && !found)
    {
        if (a[index] == x) // If the value is found
        {
            found = true;          // Set the flag 
            position = index;      // Record the value's subscript 
        }
        index++;                  // Go to the next element 
    }
    return position;             // Return the position, or -1
}

int SET::addSearchList(int a[], int length, int x) //a search for the insert function
{
    int index = 0;               // Used as a subscript to search array 
    int position = -1;           // Used to record position of search value 

    while (index < length && a[index] <= x)
    {
        index++;                  // Go to the next element 
    }
    if (index == length) //all the values were smaller than the number trying to be added
    {
        position = length; //position is at the end of the array
    }
    else
    {
        position = index; //found where to add the new element
    }
    return position;             // Return the position, or currentSize 
}

//calls the print function to print to the output stream
ostream& operator<<(ostream& os, SET& a)
{
    a.print(os);
    return os;
}

//join the two sets together
SET& operator+(SET& a, SET& b)
{
    SET added;//empty set to add to

    if (a.length == 0 && b.length != 0) //for empty sets
    {
        return b;
    }
    else if (b.length == 0 && a.length != 0) //for empty sets
    {
        return a;
    }
    else
    {
        for (int x = 0; x < a.length; x++) //add in the elements from the first set
        {
            added.insert(a.a[x]);
            cout << added.a[x] << endl;
        }

        for (int x = 0; x < b.length; x++) //add in the elements from the second set
        {
            added.insert(b.a[x]);
            cout << b.a[x] << endl;
        }

        return added; //returns the added set
    }
}

//find what the two sets have in common
SET& operator*(SET& a, SET& b)
{
    int shortestLength = 0;
    SET inCommon;

    if (a.length < b.length) //find the shortest length
    {
        shortestLength = a.length;
    }
    else
    {
        shortestLength = b.length;
    }

    //search through and find the highest common number between the sets
        for (int x = 0; x < shortestLength; x++)
        {
            for (int i = 0; i < shortestLength; i++)
            {
                if (a.a[i] == b.a[x]) //see if it shares it and has it in common
                {
                    inCommon.insert(a.a[i]); //put in the shared value
                }
            }
        }

        return inCommon; //return the common numbers
}

这是测试先前定义的不同方法的setTest.cpp:

//CSCI 205
//Brett Milinski
//Assignment 2 - The Set Class
//This problem wants us to create a set class to hold a mathematical set of integers and can later be manipulated to implement the Sieve of Eratosthenes method for computing prime numbers

#include"set.h"
#include<iostream>
using namespace std;

int main()
{
    int dummy = 0;
    SET set1(1, 7); //overloaded constructor
    SET set2, set4; //default constructor
    SET set3(5, 10);
    SET set7(9, 11);

    //testing the functions of the SET class (overloaded constructor)
    cout << set1;
    cout << "Insert 5:" << endl;
    set1.insert(5); //try inserting to end
    cout << set1;
    cout << "Try insertering 5 again:" << endl;
    set1.insert(5); //try inserting a duplicate number
    cout << set1;
    cout << "Insert 0:" << endl;
    set1.insert(0); //try inserting to start
    cout << set1;
    cout << "Erase 3:" << endl;
    set1.erase(3); //try erasing from middle
    cout << set1;
    cout << "Insert 3:" << endl;
    set1.insert(3); //try inserting to the middle
    cout << set1;
    cout << "Erase 0:" << endl;
    set1.erase(0); //try erasing from the start
    cout << set1;
    cout << "Erase 5:" << endl;
    set1.erase(5); //try erasing from the end
    cout << set1;
    cout << "Erase 20 (shouldn't work because it isn't there):" << endl;
    set1.erase(20); //try erasing something that isn't there
    cout << set1;
    cout << "Add to the empty set (set2) and then erase from it:" << endl;
    set2.insert(1); //try adding to the empty set
    cout << set2;
    set2.erase(1); //try erasing from the now populated set
    cout << set2;

    //test second set (default constructor)
    cout << "This is the default constructor (an empty set, should contain no values)." << endl;
    cout << set2;

    //try adding two overlapping sets together
    cout << "Try adding two overlapping sets together:" << endl;
    cout << "The First Set:" << endl;
    cout << set1;
    cout << "The Other Set:" << endl;
    cout << set3;
    cout << "After adding the sets together together:" << endl;
    SET set5 = set1 + set3;
    cout << set5;

    //try adding two empty sets
    cout << "Try adding two empty sets together:" << endl;
    cout << "The First Set:" << endl;
    cout << set2;
    cout << "The Other Set:" << endl;
    cout << set4;
    cout << "After adding the sets together together:" << endl;
    cout << set2 + set4;

    //try adding one filled set and one empty set
    cout << "Try adding one filled set and one empty set together:" << endl;
    cout << "The First Set:" << endl;
    cout << set1;
    cout << "The Other Set:" << endl;
    cout << set2;
    cout << "After adding the sets together together:" << endl;
    cout << set1 + set2;

    //try adding two sets that don't overlap
    cout << "Try adding two sets that don't overlap:" << endl;
    cout << "The First Set:" << endl;
    cout << set1;
    cout << "The Other Set:" << endl;
    cout << set7;
    cout << "After adding the sets together together:" << endl;
    cout << set1 + set7;

    //find out what the sets have in common
    cout << "Find what the two sets have in common:" << endl;
    cout << "The First Set:" << endl;
    cout << set1;
    cout << "The Other Set:" << endl;
    cout << set3;
    SET set6 = set1 * set3;
    cout << "The number that the two sets have in common is contained in the set below (if 0, there is no common number unless it is 0)" << endl;
    cout << set6;


    cout << "Enter a dummy number:" << endl;
    cin >> dummy;
    return 0;
}

我不确定为什么我无法做我想做的事,提前感谢我对问题的任何帮助!

2 个答案:

答案 0 :(得分:2)

这两个功能

SET& operator+(SET& a, SET& b);
SET& operator*(SET& a, SET& b);

返回对临时对象的引用:

SET& operator+(SET& a, SET& b)
{
    SET added;

    // ...

    return added;  // <= temporary object returned via a reference - don't!!
}

这些临时对象(addedinCommon)通常由编译器在堆栈上分配,并且&#34;消失&#34;当控制流离开它们定义的函数时,你最终会得到悬空引用。这是一个非常讨厌的错误。

要解决此问题,请确保按值而不是按引用返回这些对象。所需要的只是更改返回类型:

SET operator+(SET& a, SET& b);
SET operator*(SET& a, SET& b);
^^^
no more references here

答案 1 :(得分:1)

除问题mentioned by @WhiteViking外,您的

声明
//Populate Currently Allocated Reasource for each customer
for (i = 0; i < NUMBER_OF_CUSTOMERS; i++) 
{
    printf("%d:[ ",i);
    for (j = 0; j < NUMBER_OF_RESOURCES; j++)
    {
        allocation[i][j] = maximum[i][j] ? (rand() % maximum[i][j]) : 0;
        printf("%d ",allocation[i][j]);
    }
    printf("] \n\n");
}

应该是

friend ostream& operator<<(ostream& os, SET& a);

因为否则您将无法将rvalues(即临时对象)绑定到参数friend ostream& operator<<(ostream& os, const SET& a); 。在代码的第a行中,std::cout << set1 + set2;的第二个参数是右值operator<<,它只能绑定到右值引用或set1 + set2引用。实施这些更改后,您就可以使用const而不会出现任何问题。