简体   繁体   中英

“undefined reference to” operator overloading in C++

I want to create class Q(rational numbers), which have the following functions:

1)print(): printing rational number in form :numerator/denominator

2)cancel(): performs cancelation, if it's possible: (3/9 = 1/3)

3)value(): value of the rational number as double type;

4)Operator overloading with addition, subtraction, division, multiplication.

Here is my code:

#include <iostream>
#include <vector>
#include <string>
#include <stdexcept>
using namespace std;


class Q{
private:
    int num;
    int denom;

public:
    Q();
    Q(int num,int denom);
    void print();
    Q cancel();
    void value();
    friend Q operator*(Q lhs,Q rhs);
    friend Q operator/(Q lhs,Q rhs);
    friend Q operator+(Q lhs,Q rhs);
    friend Q operator-(Q lhs,Q rhs);
};

Q::Q(int numerator,int denominator){
    num = numerator;
    denom = denominator;
}


void Q::print(){
    cout << to_string(num) + "/" + to_string(denom);
}

Q Q::cancel(){
    vector<int> canc_val = {2,3,5,7};
    while(true){
        if(num % canc_val[0] == 0 && denom % canc_val[0] == 0){
            num /= canc_val[0];
            denom /= canc_val[0];
        } else if(num % canc_val[1] == 0 && denom % canc_val[1] == 0){
            num /= canc_val[1];
            denom /= canc_val[1];
        } else if(num % canc_val[2] == 0 && denom % canc_val[2] == 0){
            num /= canc_val[2];
            denom /= canc_val[2];
        }else if(num % canc_val[3] == 0 && denom % canc_val[3] == 0){
            num /= canc_val[3];
            denom /= canc_val[3];
        }else{
            break;
        }
    }
    return Q(num,denom);
}

void Q::value(){
    double res;
    res = num/denom;
    cout << res;
}

Q operator*(Q lhs,Q rhs){
    Q temp;
    temp.num = lhs.num * rhs.num;
    temp.denom = lhs.denom * rhs.denom;
    return temp;
}

Q operator/(Q lhs,Q rhs){
    Q temp;
    temp.num = lhs.num * rhs.denom;
    temp.denom = lhs.denom * rhs.num;
    return temp;
}

Q operator+(Q lhs,Q rhs){
    Q temp;
    temp.num = lhs.num * rhs.denom + rhs.num*lhs.denom;
    temp.denom = lhs.denom * rhs.denom;
    return temp;
}

Q operator-(Q lhs,Q rhs){
    Q temp;
    temp.num = lhs.num * rhs.denom - rhs.num*lhs.denom;
    temp.denom = lhs.denom * rhs.denom;
    return temp;
}

int main(){
    Q number_1(3,7);
    Q number_2(3,9);
    Q number_3(15,125);

    number_1.print();
    cout << "\n";
    number_2.print();
    number_2.cancel();
    cout << "\n";
    number_2.print();
    cout << "\n";
    number_3.value();
    cout << "\n";
    number_3.cancel();
    cout << "\n";
    number_3.print();

    Q number_4 = number_1 + number_2;
    number_4.print();
    number_4.cancel();
    cout << "\n";
    number_4.print();

    Q number_5 = number_2 - number_3;
    number_5.print();
    number_5.cancel();
    cout << "\n";
    number_5.print();


    Q number_6 = number_1 * number_1;
    number_6.print();
    number_6.cancel();
    cout << "\n";
    number_6.print();

    Q number_7 = number_2 / number_3;
    number_7.print();
    number_7.cancel();
    cout << "\n";
    number_7.print();

}

But compiler throws me an error:

/tmp/cce4zPM4.o: In function `operator*(Q&, Q&)':
:(.text+0x170): undefined reference to `Q::Q()'
/tmp/cce4zPM4.o: In function `operator/(Q&, Q&)':
:(.text+0x1b0): undefined reference to `Q::Q()'
/tmp/cce4zPM4.o: In function `operator+(Q&, Q&)':
:(.text+0x1f0): undefined reference to `Q::Q()'
/tmp/cce4zPM4.o: In function `operator-(Q&, Q&)':
:(.text+0x230): undefined reference to `Q::Q()'
collect2: error: ld returned 1 exit status

I have no idea how to fix it. Can you help me ?

There is no definition for Q::Q() , only a declaration, but you must provide a definition, like this:

Q::Q() :
    num(0),
    denom(1)
{
}

Don't just define it without an initialisation list, because this would mean that your data members have indeterminate values, eventually causing undefined behaviour.

This happens because you never implemented Q::Q() constructor.

Fortunately, you can rewrite your code to avoid using this constructor by calling Q::Q(int, int) instead.

Here is operator+ implementation example:

Q operator+(const Q& lhs, const Q& rhs) {
    return Q(lhs.num * rhs.denom + rhs.num*lhs.denom, lhs.denom * rhs.denom);
}

Note the use of const Q& instead of Q to avoid copying objects.

Consider removing Q::Q() constructor, because it is not clear what number it should represent. Perhaps you could also alter the two-argument constructor to default denominator to 1 :

Q(int num, int denom = 1);

This would let you create integers without specifying a denominator.

You should also consider normalizing your number in the constructor by dividing out GCD(num, denom) from both sides. This would make it easier to compare rational numbers in code.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM