2015-10-17 47 views
1

对于这个程序,我想创建一个SET类,其中包含一组正数和不重复的数学集合。在创建SET类之后,我创建了重载运算符,用于+和*以将两个集合添加到一起,并分别找到两个集合的相交编号。然而,在我开始测试代码之后,我发现+和*重载操作符不能在包含数字的两组数据上工作,除非我创建了一个新的SET来输出数据。例如,我不得不这样做:带类的C++重载操作符

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; 
} 

我不知道为什么我不能做我想做的事,在此先感谢对我的问题的任何帮助!

+0

什么是错误信息? – Downvoter

+3

这是很多代码。你能简化它到一个最小的例子,演示你遇到的问题吗? – user3553031

回答

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)由编译器通常被分配在堆栈上和“消失”当控制流离开它们被定义的函数时,你最终得到悬挂引用。这是一个非常讨厌的错误。

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

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

感谢您的意见。我给出的作业单据称将它们作为参考,但我可以看到你所说的是做到这一点的正确方法。我一定会和老师谈谈这件事,再次感谢! – user2922247

1
从问题 mentioned by @WhiteViking

除此之外,您的

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

声明应该是

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

否则你不会能够将rvalues(即临时对象)绑定到参数a。在代码中,在行std::cout << set1 + set2;中,operator<<的第二个参数是右值set1 + set2,它只能绑定到右值引用或const引用。一旦实施这些更改,您将可以使用std::cout << set1 + set2;,而不会有任何问题。