-1

I just learned that I can define function function in separate files than main.cpp as long as I declared the function in main.cpp and compile it using g++ main.cpp message.cpp.

But what if I want to define a class in separate files than main.cpp? It doesn't seems to work and I don't know what to declare in main.cpp while defining that class in separate files. Thanks.


Edit:

Here is main.cpp code:

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

int main() {
  int a, b;
  string str;
  Fraction fract;
  while (true) {
    cout << "Enter numerator: ";
    cin >> a;
    cout << "Enter denumerator: ";
    cin >> b;
    fract.set(a, b);
    cout << "Numerator is " << fract.get_num()
     << endl;
    cout << "Denumerator is " << fract.get_den()
     << endl;
    cout << "Do it again? (y or n) ";
    cin >> str;
    if (!(str[0] == 'y'))
      break;
  }
  return 0;
}

And here is Fraction.cpp

#include <cstdlib>

class Fraction {
private:
  int num, den;
public:
  void set(int n, int d) {
    num = n;
    den = d;
    normalize();
  }
  int get_num() {
    return num;
  }
  int get_den() {
    return den;
  }
private:
  void normalize() {
    if (den == 0 || num == 0) {
      num = 0;
      den = 1;
    }
    if (den < 0) {
      num *= -1;
      den *= -1;
    }
    int n = gcf(num, den);
    num = num / n;
    den = den / n;
  }
  int gcf(int a, int b) {
    if (b == 0)
      return abs(a);
    else
      return gcf(b, a%b);
  }
  int lcm(int a, int b) {
    int n = gcf(a, b);
    return a / n * b;
  }
};

But I can't compile it with g++ main.cpp Fraction.cpp.


Edit2:

It gives me error:

main.cpp: in function 'int main()':
main.cpp:8:3: error: 'Fraction' was not declared in this scope
main.cpp:14:15: 'fract' was not declared in this scope
user312781
  • 41
  • 5
  • Please post a [Minimal, Complete, and Verifiable example](http://stackoverflow.com/help/mcve). – R Sahu Oct 10 '18 at 21:55
  • @RSahu sorry I ask question with mobile apps, but I just edited, need help – user312781 Oct 10 '18 at 22:01
  • 3
    You need to create a`Fraction.h` file and include that from main.cpp and fraction.cpp. The problem is you defined all of your functions in the class declaration so the .cpp file will not have anything. – drescherjm Oct 10 '18 at 22:03
  • @drescherjm whooaaa genius man, that works thanks so much, just renamed Fraction.cpp to Fraction.h and add `#include "Fraction.h"` strangely it works smoothly. But how can I make it so it just Fraction.cpp for more consistency? – user312781 Oct 10 '18 at 22:12
  • No. You don't want to do that. You want to create a `Fraction.cpp` file. And move some of your class members from your class declaration to your `Fraction.cpp` file. I would say that `normalize()` probably should be moved. – drescherjm Oct 10 '18 at 22:14
  • @drescherjm well that sounds more complicated than just making it `Fraction.h`. Well I think I'll just stick to `Fraction.h`. Thanks so much mann... worked perfectly – user312781 Oct 10 '18 at 22:17
  • I will post an example. – drescherjm Oct 10 '18 at 22:19
  • @drescherjm whoaa... sure thanks, can you do it in formal answer? – user312781 Oct 10 '18 at 22:20
  • It'll probably be infiormal. It's hard to get people to use the proper "thee"s and "thou"s these days. And people end sentences with prepositions, the barbarians. – user4581301 Oct 10 '18 at 22:23

1 Answers1

2

I would create a Fraction.h file containing your class

#ifndef FRACTION_H
#define FRACTION_H

class Fraction {
private:
  int num, den;
public:
  void set(int n, int d) {
    num = n;
    den = d;
    normalize();
  }
  int get_num() {
    return num;
  }
  int get_den() {
    return den;
  }
private:
   void normalize();
   int gcf(int a, int b);
   int lcm(int a, int b);
};

#endif //ndef FRACTION_H   

Then Fraction.cpp containing

#include "Fraction.h"
void Fraction::normalize() {
  if (den == 0 || num == 0) {
    num = 0;
    den = 1;
  }
  if (den < 0) {
    num *= -1;
    den *= -1;
  }
  int n = gcf(num, den);
  num = num / n;
  den = den / n;
}

int Fraction::gcf(int a, int b) {
  if (b == 0)
    return abs(a);
  else
    return gcf(b, a%b);
}

int Fraction::lcm(int a, int b) {
  int n = gcf(a, b);
  return a / n * b;
}

Then in main.cpp make sure you add

#include "Fraction.h"

to your includes

The main reason I moved the larger functions from the class declaration to the Fraction.cpp was to keep the interface clean. However there are several other reasons to consider what member functions to implement in the header versus the translation unit.

The following question discusses that in more detail: Why have header files and .cpp files?

In the comments there was a question on the purpose of the #ifndef FRACTION_H these are include guards. A good discussion on what these are used for are here: Why are #ifndef and #define used in C++ header files?

drescherjm
  • 10,365
  • 5
  • 44
  • 64
  • Upped, but recommend adding a few words on, or a link to, the selection criteria explaining which functions should be included in or removed from the class definition. – user4581301 Oct 10 '18 at 22:26
  • 1
    And [maybe a note on what a header file is and why we split them all up](https://stackoverflow.com/questions/333889/why-have-header-files-and-cpp-files). – user4581301 Oct 10 '18 at 22:28
  • It sure works thankss, but what does `#ifndef` and `#define` do? Sorry to bother you, this is new to me... – user312781 Oct 10 '18 at 22:29
  • #ifndef is used here for an include guard. – drescherjm Oct 10 '18 at 22:30
  • @user4581301 whoa thanks to link it , just just know that header specifically means for class declaration, I thought I use it to make a bunch of functions – user312781 Oct 10 '18 at 22:33
  • One thing I don't like with this code is you don't have a constructor. – drescherjm Oct 10 '18 at 22:44
  • @user312781 it's a bit deeper than just class goes in the header. Read the second answer at that link because it covers what's up in much greater detail. Think of it as the interface, the "What can I do with this code?", goes in the header. The *What* goes into the header and the *How* goes into the cpp. Generally an interface doesn't change much. The code that implements the interface, that's changing all the time as people figure out how to make it better. – user4581301 Oct 10 '18 at 23:10
  • 1
    When you bundle the interface with the implementation, any change to the implementation ripples through the entire system even though nothing the rest of the system cares about changed. – user4581301 Oct 10 '18 at 23:11