2016-08-20 61 views
-2

我一直试图用2个自定义类Fraction和Integer来重载+运算符。我理想地喜欢+运算符来返回最简单的操作版本(即1/4 + 3/4 == 1(整数))。我还没有找到动态分配返回类型的好方法,所以我试图返回包含在Struct或元组中的多个值。我encouter段错误实际尝试在主操作时,如下所示:Segfault返回一个元组

///main///////// 
int main(){ 
    Fraction *f = new Fraction(1,4); 
    Fraction *f2 = new Fraction(3,4); 
    Fraction *resF = new Fraction();//results 
    Integer *resI = new Integer(); 

    boost::tie(resF, resI) = *f+*f2; //SEGFAULT here 
} 

涉及的两个类是一个共同的抽象基类的deriviatives,用这里定义的部件及功能:

#include <boost/tuple/tuple.hpp> 
#include <iostream> 
//Number class 
//forward declarations for tuple 
class Integer; 
class Fraction; 
//abstract base class 
template<class T>//T is derived class 
class Number{ 
    virtual const boost::tuple<Fraction*, Integer*> operator+ (const Number&) {}; 
    virtual void display(std::ostream &) const {} ; 
    virtual bool operator==(const Number& rhs) const{} ; 
};//end of Number class 

//Integer class 
class Integer: public Number<Integer>{ 
    int numericValue;//<! the value of the integer 
    public: 
    int getValue() const;//<!access private member variable numericValue 
    void setValue(int);//<!set private member variable numericValue 
    Integer();//<!default constructor 
    Integer(int);//<!param constructor 
    virtual ~Integer() {}//<!destructor 
    //display 
    void display(std::ostream &) const;//<!stream a display of the number 
    //int == int 
    bool operator==(const Integer&) const;//<! comparator int-int 
    // int + int 
    const Integer operator+ (const Integer &);//<! add int+int 
}; 
//DEFINITIONS//////////////////// 
//Default constructor 
Integer::Integer(){ 
    numericValue = 0; 
} 
// param constructor 
Integer::Integer(int num){ 
    numericValue = num; 
} 
//get integer value 
int Integer::getValue() const{ 
    return this->numericValue; 
} 
//set integer value 
void Integer::setValue(int x){ 
    this->numericValue = x; 
} 
//display int 
void Integer::display(std::ostream& stream) const{ 
    stream << this->numericValue<<std::endl; 
} 
// int + int 
const Integer Integer::operator+(const Integer &rhs){ 
    Integer temp = this->numericValue + rhs.numericValue; 
    return temp; 
} 
// int == int 
bool Integer::operator==(const Integer& rhs) const{ 
    if(this->numericValue == rhs.numericValue) 
    return true; 
    else 
    return false; 
} 
//end of Integer class 

//Fraction class 
class Fraction: public Number<Fraction>{ 
    Integer numerator; 
    Integer denominator; 

    boost::tuple<Fraction*, Integer*> resOfAdd; 

    public: 
    int getNumerator();//<! to access private member 
    int getDenominator();//<! to access private member 
    bool isInteger;//<! flag if the fraction result of '+' can be reduced as an integer 
    bool isWhole();//!<tells if can be simplified to integer 
    Integer fToI;//<! store the integer value of the fraction if it is whole 
    Fraction() = default;//<! default constructor 
    Fraction(const int &, const int &);//<!param constructor 
    const Fraction simplify(const Fraction &in);//<! simplifies fraction if possible 
    int gcdCalculate(int lhs, int rhs);//!<greatest common denominator 
    int lcmCalculate(const int lhs, const int rhs);//<!least common 
    virtual ~Fraction() {} 
    //display 
    void display(std::ostream &) const; 
    // frac == frac 
    bool operator==(const Fraction& rhs) const; 
    //frac + frac 
    boost::tuple<Fraction*, Integer*> operator+(const Fraction &); 
};//end of Fraction class 
//DEFINITIONS/////////////////// 
// param constructor 
Fraction::Fraction(const int & num, const int & den){ 
    numerator.setValue(num); 
    denominator.setValue(den); 
    if(denominator.getValue()==1){//also an integer 
    fToI = Integer(numerator.getValue()); 
    } 
    if(denominator.getValue() < 0 && numerator.getValue() > 0){//negative sign on bottom 
    denominator.setValue(denominator.getValue()*-1); 
    numerator.setValue(numerator.getValue()*-1); //switch it to the top 
    } 
    if(denominator.getValue() < 0 && numerator.getValue() < 0){//both top and bottom are negative 
    denominator.setValue(denominator.getValue()*-1); 
    numerator.setValue(numerator.getValue()*-1); //flip them to positive 
    } 
} 
//get ifInteger 
bool Fraction::isWhole(){ 
    return this->isInteger; 
} 
//get numerator 
int Fraction::getNumerator(){ 
    return this->numerator.getValue(); 
} 
//get denominator 
int Fraction::getDenominator(){ 
    return this->denominator.getValue(); 
} 
// display the fraction value 
void Fraction::display(std::ostream & stream) const{ 
    stream << this->numerator.getValue() << "/" << this->denominator.getValue()<<std::endl; 
} 
//simplify fraction 
const Fraction Fraction::simplify(const Fraction &in){ 
    int gcd = gcdCalculate(in.numerator.getValue(), in.denominator.getValue()); 
    Fraction res = Fraction(in.numerator.getValue()/gcd, in.denominator.getValue()/gcd); 
    return res; 
} 
//lcm - least common multiplier 
int Fraction::lcmCalculate(const int lhs, const int rhs){ 
    int temp = gcdCalculate(lhs, rhs); 
    return temp ? (lhs/temp * rhs) : 0; 
} 
//gcd - greatest common divisor 
int Fraction::gcdCalculate(int a, int b){ 
    return b == 0 ? a : gcdCalculate(b, a % b); 
} 

//frac + frac -- causing problem 
boost::tuple<Fraction*, Integer*>/*numRep<Fraction, Integer>*/ Fraction::operator+(const Fraction &rhsIn){ 
    int numRes, denRes; 
    Fraction* resF; 
    Integer* resI; //if there is an integer result 
    //simplify input 
    Fraction lhs = simplify(*this); 
    Fraction rhs = simplify(rhsIn); 
    int lcm = lcmCalculate(lhs.denominator.getValue(), rhs.denominator.getValue()); 
    int gcd = gcdCalculate(lhs.denominator.getValue(), rhs.denominator.getValue()); 
    //share denominator? 
    if(lhs.denominator.getValue() == rhs.denominator.getValue()){ 
    numRes = lhs.numerator.getValue() + rhs.numerator.getValue();//simply add the numerators 
    denRes = lhs.denominator.getValue();//keep denominator 
    } 
    else{ 
    // a1 a2 a1*b2+a2*b1 
    // -- + -- = ----------- 
    // b1 b2  b1*b2 
    int a1 = lhs.getNumerator(); 
    int b1 = lhs.getDenominator(); 
    int a2 = rhs.numerator.getValue(); 
    int b2 = rhs.denominator.getValue(); 
    numRes = a1*b2 + a2*b1; 
    denRes = b1*b2; 
    } 
    *resF = Fraction(numRes, denRes); 
    //simplify 
    *resF = simplify(*resF); 
    if(resF->denominator.getValue() == 1){//integer result 
    resF->isInteger = true;//flag 
    fToI = Integer(resF->numerator.getValue());//make Integer 
    resI = &fToI; //return the integer when you can 
    } 
    else{ 
    resI = new Integer(0); 
    } 
    //put the fraction and the (possible) integer representations into a number struct 
    resOfAdd = boost::make_tuple(resF, resI); 

    std::cout<<" + = "; 
    resF->display(std::cout); 
    delete resF; 
    delete resI; 
    return resOfAdd; 
} 

我必须使用结构和元组来获得相同的段错误是错误的。任何人都可以建议我的错误,或建议一个替代/优越的解决方案来动态地分配返回值?我明白,动态灵活的返回类型可能是不可能的。感谢您的时间和帮助。

+3

请发布[mcve] –

+0

您的段错误发生在哪里? – UnholySheep

+1

我很惊讶你没有得到未使用的变量警告。你似乎也有很多不必要的指针。 – chris

回答

1
Fraction* resf; 
... 
*resf = 

resf是未初始化的指针,而你正试图复制分配的东西所指向的位置。

在这里返回一个指针是一个坏主意,因为它引入了所有权语义。刚刚返回值:

boost::tuple<Fraction, Integer> ... 

如果你使用指针,所以你可能表明整数是否存在与否,可以考虑使用boost::optional

+0

谢谢!这是很好的建议,并解决了我的问题。感谢大家的洞察力和帮助。 – ieddd