0

I'm trying to complete a homework project for my computer science class. I have a - at least to me perplexing problem of "multiple definitions" at each and every one of my single definitions in my implementation file. My header is as follows:

#ifndef FRACTION_H
#define FRACTION_H

using namespace std;

class fraction
{
    public:
    fraction (int n = 1, int d = 4);    // constructor with 2 default params
    ~fraction();                        // destructor explained more in class
    fraction add(fraction);             // adds two fractions returning a third
    fraction subtract(fraction);        // subtracts two fractions returning third
    fraction multiply(fraction);        // multiplies two fractions returning third
    fraction divide(fraction);          // divides two fractions returning a third
    fraction makeFraction(double);          // converts any decimal to a fraction
    fraction makeImproperFraction(int, fraction); // make a mixed fraction -> improper
    fraction getInverse() const;        // swaps the numerator and denominator
    fraction reduce();                  // reduces the fraction to lowest terms

    double getDecimal() const;          // return fraction's decimal equivalent;
    void setNumer(int);                 // sets the private member numerator
    void setDenom(int);                 // sets the private member denominator
    int getNumer() const;               // gets the private member numerator
    int getDenom() const;               // gets the private member denominator
    void print() const;                 // overloaded print the fraction to the console
    void print(ostream&) const;         // overloaded print the fraction to the file

    private:
    int numerator;                      // private int member for numerator
    int denominator;                    // private int member for denominator
    int gcf(int, int);                  // private function for greatest common factor
};

#endif // FRACTION_H

Then I have my implementation file...

#include <iostream>
#include <iomanip>
#include <fstream>
#include "fraction.h"

// constructor with 2 parameters
fraction::fraction(int n, int d)
{
    // check for a negative denominator & adjust
    if(d <= 0)
    {
        denominator = -d;   // uses a unary operator to change the sign
        numerator = -n;     //  "   "   "       "    "     "    "   "
    }
    else if (d == 0)
    {
        cout << "Input error!  Denominator cannot be zero!" << endl;
        return;
    }
    else
    {
        denominator = d;
        numerator = n;
    }
}

// destructor (not used for now)  ... so why define it?  why mention it?
fraction::~fraction()
{
}

// reads in the appropriate value from the file and returns the value to be used as numer.
int fraction::getNumer() const
{
    ifstream myInput("fractionIn.txt");
    int numerator;                  // Declare variable to be returned
    if (myInput.is_open()){         // Check to make sure file opened correctly
        myInput >> numerator;       // Reads in next available value into the numerator
    }
    else {
        cout << "There was an error opening the file!" << endl << endl;
    }
    return numerator;
}

// ...........
int fraction::getDenom() const
{
    ifstream myInput("fractionIn.txt");
    int denominator;                  // Declare variable to be returned
    if (myInput.is_open()){           // Check to make sure file opened correctly
        myInput >> denominator;       // Reads in next available value into the denominator
    }
    else {
        cout << "There was an error opening the file!" << endl << endl;
    }
    return denominator;
}

// Find the sum of the fraction with the parameter fraction.
// Returns the sum of the two fractions
fraction fraction::add(fraction a)
{
    int num1 = numerator * a.denominator;       // local numer1 to this fradtion
    int num2 = a.numerator * denominator;       // local numer2 to this fraction
    int denom = denominator * a.denominator;    // local common denominator to both
    fraction result(num1 + num2, denom);        // local fraction object
    int gcfResult = fraction::gcf(result.numerator, result.numerator);  //Find gcf for result
    result.numerator = result.numerator / gcfResult;                    //Divide both sides by gcf
    result.denominator = result.denominator / gcfResult;                //  "      "    "   "   "
    return result;                              // return the local fraction
}

// Find the difference of the fraction with the parameter fraction.
// Returns the difference of the two fractions
fraction fraction::subtract(fraction a)
{
    int num1 = numerator * a.denominator;       // local numer1 to this fradtion
    int num2 = a.numerator * denominator;       // local numer2 to this fraction
    int denom = denominator * a.denominator;    // local common denominator to both
    fraction result(num1 -  num2, denom);        // local fraction object
    int gcfResult = fraction::gcf(result.numerator, result.numerator);  //Find gcf for result
    result.numerator = result.numerator / gcfResult;                    //Divide both sides by gcf
    result.denominator = result.denominator / gcfResult;                //  "      "    "   "   "
    return result;                              // return the local fraction
}

// Find the product of the fraction with the parameter fraction.
// Returns the product of the two fractions
fraction fraction::multiply(fraction a)
{
    int numer = numerator * a.numerator;       // local common numerator to both fractions
    int denom = a.denominator * denominator;   // local common denominator to both
    fraction result(numer, denom);     // local fraction object
    int gcfResult = fraction::gcf(result.numerator, result.numerator);  //Find gcf for result
    result.numerator = result.numerator / gcfResult;                    //Divide both sides by gcf
    result.denominator = result.denominator / gcfResult;                //  "      "    "   "   "
    return result;                              // return the local fraction
}

// Find the quotient of the fraction with the parameter fraction.
// Returns the quotient of the two fractions
fraction fraction::divide(fraction a)
{
    int numer = numerator * a.denominator;       // local common numerator to both fractions
    int denom = a.numerator * denominator;   // local common denominator to both
    fraction result(numer, denom);     // local fraction object
    int gcfResult = fraction::gcf(result.numerator, result.numerator);  //Find gcf for result
    result.numerator = result.numerator / gcfResult;                    //Divide both sides by gcf
    result.denominator = result.denominator / gcfResult;                //  "      "    "   "   "
    return result;                              // return the local fraction
}

// gcf returns the greatest common factor
// used to reduce fractions
int fraction::gcf(int n, int d)                 // uses Euler's gcf algorithm
{
    int resGCF;                                 // declaration of result GCF
    int remainder = 0;                          // initialize remainder to zero

    while (d != 0)                              // loops until denominator == 0
    {
        remainder = n % d;                      //    remainder of the n/d division
        n = d;                                  //    assign denominator to numerator
        d = remainder;                          //    assign remainder to denominator
    }                                           // end of while loop

    resGCF = n;                                 // assign numerator to result GCF
    return resGCF;                              // return result GCF
}
//make a mixed fraction -> improper
//Returns an improper fraction
fraction fraction::makeImproperFraction(int a, fraction b) {
    a *= b.denominator;                             //Multiply whole number by denominator to set it to proper value
    b.numerator += a;                               //Add new value for modified whole number to numerator for improper fraction
    fraction result (b.numerator, b.denominator);   //store new numerator over original denominator into the result
    int gcfResult = fraction::gcf(result.numerator, result.numerator);  //Find gcf for result
    result.numerator = result.numerator / gcfResult;                    //Divide both sides by gcf
    result.denominator = result.denominator / gcfResult;                //  "      "    "   "   "
    return result;                                                   //Return this result
}
fraction fraction::reduce() {
    fraction result (numerator, denominator);
    int gcfResult = fraction::gcf(result.numerator, result.numerator);  //Find gcf for result
    result.numerator = result.numerator / gcfResult;                    //Divide both sides by gcf
    result.denominator = result.denominator / gcfResult;
    return result;
}

The issue is that Code::Blocks keeps telling me that there are "multiple definitions" for each and every one of my member function definitions, even though as far as I can tell, there is only one a piece... The error log is pasted below

||=== Build: Debug in lab1redux (compiler: GNU GCC Compiler) ===|
obj\Debug\fractionTest.o||In function `ZN8fractionC2Eii':|
C:\Users\user\OneDrive - VCCS Student Advantage\School Work\CSC210\Lab1 Redux\lab1redux\fraction.cpp|14|multiple definition of `fraction::fraction(int, int)'|
obj\Debug\fraction.o:C:\Users\user\OneDrive - VCCS Student Advantage\School Work\CSC210\Lab1 Redux\lab1redux\fraction.cpp|14|first defined here|
obj\Debug\fractionTest.o||In function `ZN8fractionC2Eii':|
C:\Users\user\OneDrive - VCCS Student Advantage\School Work\CSC210\Lab1 Redux\lab1redux\fraction.cpp|14|multiple definition of `fraction::fraction(int, int)'|
obj\Debug\fraction.o:C:\Users\user\OneDrive - VCCS Student Advantage\School Work\CSC210\Lab1 Redux\lab1redux\fraction.cpp|14|first defined here|
obj\Debug\fractionTest.o||In function `ZN8fractionD2Ev':|
C:\Users\user\OneDrive - VCCS Student Advantage\School Work\CSC210\Lab1 Redux\lab1redux\fraction.cpp|35|multiple definition of `fraction::~fraction()'|
obj\Debug\fraction.o:C:\Users\user\OneDrive - VCCS Student Advantage\School Work\CSC210\Lab1 Redux\lab1redux\fraction.cpp|35|first defined here|
obj\Debug\fractionTest.o||In function `ZN8fractionD2Ev':|
C:\Users\user\OneDrive - VCCS Student Advantage\School Work\CSC210\Lab1 Redux\lab1redux\fraction.cpp|35|multiple definition of `fraction::~fraction()'|
obj\Debug\fraction.o:C:\Users\user\OneDrive - VCCS Student Advantage\School Work\CSC210\Lab1 Redux\lab1redux\fraction.cpp|35|first defined here|
obj\Debug\fractionTest.o||In function `ZNK8fraction8getNumerEv':|
C:\Users\user\OneDrive - VCCS Student Advantage\School Work\CSC210\Lab1 Redux\lab1redux\fraction.cpp|41|multiple definition of `fraction::getNumer() const'|
obj\Debug\fraction.o:C:\Users\user\OneDrive - VCCS Student Advantage\School Work\CSC210\Lab1 Redux\lab1redux\fraction.cpp|41|first defined here|
obj\Debug\fractionTest.o||In function `ZNK8fraction8getDenomEv':|
C:\Users\user\OneDrive - VCCS Student Advantage\School Work\CSC210\Lab1 Redux\lab1redux\fraction.cpp|55|multiple definition of `fraction::getDenom() const'|
obj\Debug\fraction.o:C:\Users\user\OneDrive - VCCS Student Advantage\School Work\CSC210\Lab1 Redux\lab1redux\fraction.cpp|55|first defined here|
obj\Debug\fractionTest.o||In function `ZN8fraction3addES_':|
C:\Users\user\OneDrive - VCCS Student Advantage\School Work\CSC210\Lab1 Redux\lab1redux\fraction.cpp|70|multiple definition of `fraction::add(fraction)'|
obj\Debug\fraction.o:C:\Users\user\OneDrive - VCCS Student Advantage\School Work\CSC210\Lab1 Redux\lab1redux\fraction.cpp|70|first defined here|
obj\Debug\fractionTest.o||In function `ZN8fraction8subtractES_':|
C:\Users\user\OneDrive - VCCS Student Advantage\School Work\CSC210\Lab1 Redux\lab1redux\fraction.cpp|84|multiple definition of `fraction::subtract(fraction)'|
obj\Debug\fraction.o:C:\Users\user\OneDrive - VCCS Student Advantage\School Work\CSC210\Lab1 Redux\lab1redux\fraction.cpp|84|first defined here|
obj\Debug\fractionTest.o||In function `ZN8fraction8multiplyES_':|
C:\Users\user\OneDrive - VCCS Student Advantage\School Work\CSC210\Lab1 Redux\lab1redux\fraction.cpp|98|multiple definition of `fraction::multiply(fraction)'|
obj\Debug\fraction.o:C:\Users\user\OneDrive - VCCS Student Advantage\School Work\CSC210\Lab1 Redux\lab1redux\fraction.cpp|98|first defined here|
obj\Debug\fractionTest.o||In function `ZN8fraction6divideES_':|
C:\Users\user\OneDrive - VCCS Student Advantage\School Work\CSC210\Lab1 Redux\lab1redux\fraction.cpp|111|multiple definition of `fraction::divide(fraction)'|
obj\Debug\fraction.o:C:\Users\user\OneDrive - VCCS Student Advantage\School Work\CSC210\Lab1 Redux\lab1redux\fraction.cpp|111|first defined here|
obj\Debug\fractionTest.o||In function `ZN8fraction3gcfEii':|
C:\Users\user\OneDrive - VCCS Student Advantage\School Work\CSC210\Lab1 Redux\lab1redux\fraction.cpp|124|multiple definition of `fraction::gcf(int, int)'|
obj\Debug\fraction.o:C:\Users\user\OneDrive - VCCS Student Advantage\School Work\CSC210\Lab1 Redux\lab1redux\fraction.cpp|124|first defined here|
obj\Debug\fractionTest.o||In function `ZN8fraction20makeImproperFractionEiS_':|
C:\Users\user\OneDrive - VCCS Student Advantage\School Work\CSC210\Lab1 Redux\lab1redux\fraction.cpp|140|multiple definition of `fraction::makeImproperFraction(int, fraction)'|
obj\Debug\fraction.o:C:\Users\user\OneDrive - VCCS Student Advantage\School Work\CSC210\Lab1 Redux\lab1redux\fraction.cpp|140|first defined here|
obj\Debug\fractionTest.o||In function `ZN8fraction6reduceEv':|
C:\Users\user\OneDrive - VCCS Student Advantage\School Work\CSC210\Lab1 Redux\lab1redux\fraction.cpp|149|multiple definition of `fraction::reduce()'|
obj\Debug\fraction.o:C:\Users\user\OneDrive - VCCS Student Advantage\School Work\CSC210\Lab1 Redux\lab1redux\fraction.cpp|149|first defined here|
||error: ld returned 1 exit status|
||=== Build failed: 27 error(s), 0 warning(s) (0 minute(s), 3 second(s)) ===|

What is going on here? I cannot for the life of me put my finger on what is causing this issue. I've checked to make sure I've not defined it multiple times. I've reduced my main.cpp down to nothing more than a return to try and minimize the issue, removing members, etc and I'm at a loss.

Also I understand that there are some "unapproved" tactics used in the header such as the "using namespace std;" that's out of my control; professor wants us to use the header file as-is in order to complete the task, not modifying any of the members or content therein.

jww
  • 97,681
  • 90
  • 411
  • 885
  • Do you possibly have another source file named "fractionTest.cpp"? What's in that file? – Drew Dormann Jun 04 '18 at 03:08
  • *"C:\Users\user\OneDrive ..."* - Stop using a remote drive; use a local drive instead. Then see if you can repeat it. Be sure to completely clean the project of output artifacts. – jww Jun 04 '18 at 03:15
  • My psychic powers predict `#include "fraction.cpp"` in fractiontest.cpp – user4581301 Jun 04 '18 at 03:19
  • @DrewDormann it serves as the project's "main.cpp." It includes iostream, iomanip, fstream, fraction.cpp (not the header, just the implementation), and then to make it as simple as possible to diagnose this problem, it declares int main() and then returns it with no actual code. – CaptainDredlokk Jun 04 '18 at 03:20
  • @jww Yep, same issue on local drive. When looking at the debugger, it gives the whole explanation of the multiple definitions and "first defined here," and then it repeats itself (saying the same exact error for the same exact line, also saying "first defined here" for each implementation, twice each.) And okay; what exactly does "output artifacts" mean however? – CaptainDredlokk Jun 04 '18 at 03:21
  • 1
    Psychic powers for the win. Do not include cpp files. Include the header and let the compiler and linker handle the cpp file. When you include a file it is effectively pasted into the including file, so everything that is in fraction cpp is compiled twice, one as part of fraction.cpp and once as part of fractionTest.cpp. The linker sees two definitions and doesn't know which to use. – user4581301 Jun 04 '18 at 03:23
  • Some good reading/ longer explanation: [Error with multiple definitions of function](https://stackoverflow.com/questions/17904643/error-with-multiple-definitions-of-function) – user4581301 Jun 04 '18 at 03:26

1 Answers1

0

The problem - you are including a cpp file from another cpp file. It is very unusual for that to be the correct choice.

Your errors are telling you that your source file fraction.cpp was compiled to define several functions. And your source file fractionTest.cpp is defining the same functions a second time. Because it is including the entire contents of fraction.cpp.

Remove this line.

#include "fraction.cpp"

If necessary, replace it with this line:

#include "fraction.h"

You do not want two cpp files to define the same function. That is a violation of the One Definition Rule.

Drew Dormann
  • 59,987
  • 13
  • 123
  • 180