2016-08-20 11 views
-2

2 개의 사용자 정의 클래스 인 Fraction 및 Integer로 + 연산자를 오버로드하려고했습니다. + 연산자가 가장 간단한 연산 버전 (즉, 1/4 + 3/4 == 1 (정수))을 반환하는 것이 이상적입니다. 동적으로 반환 형식을 할당하는 좋은 방법을 찾지 못했습니다. 그래서 Struct 또는 튜플에 포함 된 여러 값을 반환하려고했습니다. 참여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은 다음과 같습니다 : 실제로 주에 작업을 시도 할 때 다음과 같이 나는 세그먼트 폴트를 encouter

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

내가해야 구조체와 튜플을 모두 사용하여 동일한 segfault 오류를 얻으려면 잘못된 작업을 수행해야합니다. 아무도 내 실수에 대해 조언하거나 반환 값을 동적으로 할당하는 대체/우수 솔루션을 제안 할 수 있습니까? 동적으로 유연한 반환 유형을 사용하지 못할 수도 있음을 알고 있습니다. 시간과 도움에 감사드립니다.

+3

[mcve] –

+0

게시물을 보내주십시오. segfault는 어디에서 발생합니까? – UnholySheep

+1

사용하지 않는 변수 경고가 표시되지 않는다는 것에 놀랐습니다. 당신은 또한 불필요한 포인터가 많이있는 것 같습니다. – chris

답변

1
Fraction* resf; 
... 
*resf = 

resf는 초기화되지 않은 포인터이고, 당신은 그것을 가리키는 위치에 복사 지정 뭔가에 노력하고 있습니다.

여기에 포인터를 반환하는 것은 소유권 의미론을 도입하기 때문에 나쁜 생각입니다. 그냥 값으로 반환 :

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

당신이 boost::optional 사용을 고려, 정수가 존재 여부를 나타내는 여부를 수 있도록 포인터를 사용한 경우.

+0

감사합니다! 이것은 큰 조언이었고 나의 문제를 해결했습니다. 통찰력과 도움을 주신 모든 분들께 감사드립니다. – ieddd