0

I'm new to classes and object-oriented programming. Our instructor is having us create a program that must have a .cpp file, a main .cpp file, and a .hpp file.

Here are each of the files:

First, the odometer.hpp file:

class Odometer
{
    int miles;
    float gallons, mpg;

public:
    //Constructors
    Odometer(); //Default
    Odometer(float g, int m); 

    //Mutator Functions
    void Set_miles(int m);
    void Set_gallons(float g);

    //Functions
    void Add_trip(int m, float g);
    int Check_mileage(float g);
    void Print_info();

    //Accessor Functions
    float Get_mpg();
    float Get_gallons();
    int Get_miles();
};

Next, the odometer.cpp file:

#include "odometer.hpp"
#include <iostream>

//Constructors
Odometer::Odometer()
{
    miles = 0;
    gallons = 0.0;
    mpg = 0.0;
}

Odometer::Odometer(float g, int m)
{
    miles = m;
    gallons = g;
    mpg = m / g;
}

//Mutator functions
void Odometer::Set_miles(int m)
{
    miles = m;
}

void Odometer::Set_gallons(float g)
{
    gallons = float(g);
}

//Accessor functions
float Odometer::Get_mpg()
{
    return mpg;
}

float Odometer::Get_gallons()
{
    return gallons;
}

int Odometer::Get_miles()
{
    return miles;
}

//Other functions
//Takes # of gallons & # of miles and adds it to previous values, calculating
//new miles/gallon for whole trip
void Odometer::Add_trip(int m, float g)
{
    miles += m;
    gallons += g;
    mpg = miles / gallons;
}

int Odometer::Check_mileage(float g)
{
    int newMiles = g * mpg;
    return newMiles;
}

void Odometer::Print_info()
{
    std::cout << "Miles:   " << miles << "     Gallons: " << gallons << 
"     Miles/Gallon: " << mpg;
}

And finally, the odometer_main.cpp file (so far, it's incomplete):

#include <iostream>
#include "odometer.cpp"

using namespace std;

int main(void)
{
    //Odometer odDefault; //Odometer object set to defaults
    Odometer od(10, 100); //Odometer object with values set
    return 0;
}

These are the errors I'm getting when I try compiling all the files:

/tmp/ccArjYHP.o: In function 'Odometer::Odometer()':
odometer_main.cpp:(.text+0x0): multiple definition of 'Odometer::Odometer()'  
/tmp/cc1W9Ght.o:odometer.cpp:(.text+0x0): first defined here
/tmp/ccArjYHP.o: In function 'Odometer::Odometer()':
odometer_main.cpp:(.text+0x0): multiple definition of 'Odometer::Odometer()'
/tmp/cc1W9Ght.o:odometer.cpp:(.text+0x0): first defined here
/tmp/ccArjYHP.o: In function 'Odometer::Odometer(float, int)':
odometer_main.cpp:(.text+0x30): multiple definition of 'Odometer::Odometer(float, int)'
/tmp/cc1W9Ght.o:odometer.cpp:(.text+0x30): first defined here
/tmp/ccArjYHP.o: In function 'Odometer::Odometer(float, int)':
odometer_main.cpp:(.text+0x30): multiple definition of 'Odometer::Odometer(float, int)'
/tmp/cc1W9Ght.o:odometer.cpp:(.text+0x30): first defined here
/tmp/ccArjYHP.o: In function 'Odometer::Set_miles(int)':
odometer_main.cpp:(.text+0x72): multiple definition of 'Odometer::Set_miles(int)'
/tmp/cc1W9Ght.o:odometer.cpp:(.text+0x72): first defined here
/tmp/ccArjYHP.o: In function 'Odometer::Set_gallons(float)':
odometer_main.cpp:(.text+0x8a): multiple definition of 'Odometer::Set_gallons(float)'
/tmp/cc1W9Ght.o:odometer.cpp:(.text+0x8a): first defined here
/tmp/ccArjYHP.o: In function 'Odometer::Get_mpg()':
odometer_main.cpp:(.text+0xa8): multiple definition of 'Odometer::Get_mpg()'
/tmp/cc1W9Ght.o:odometer.cpp:(.text+0xa8): first defined here
/tmp/ccArjYHP.o: In function 'Odometer::Get_gallons()':
odometer_main.cpp:(.text+0xbc): multiple definition of 'Odometer::Get_gallons()'
/tmp/cc1W9Ght.o:odometer.cpp:(.text+0xbc): first defined here
/tmp/ccArjYHP.o: In function 'Odometer::Get_miles()':
odometer_main.cpp:(.text+0xd0): multiple definition of 'Odometer::Get_miles()'
/tmp/cc1W9Ght.o:odometer.cpp:(.text+0xd0): first defined here
/tmp/ccArjYHP.o: In function 'Odometer::Add_trip(int, float)':
odometer_main.cpp:(.text+0xe0): multiple definition of 'Odometer::Add_trip(int, float)'
/tmp/cc1W9Ght.o:odometer.cpp:(.text+0xe0): first defined here
/tmp/ccArjYHP.o: In function 'Odometer::Check_mileage(float)':
odometer_main.cpp:(.text+0x140): multiple definition of 'Odometer::Check_mileage(float)'
/tmp/cc1W9Ght.o:odometer.cpp:(.text+0x140): first defined here
/tmp/ccArjYHP.o: In function 'Odometer::Print_info()':
odometer_main.cpp:(.text+0x168): multiple definition of 'Odometer::Print_info()'
/tmp/cc1W9Ght.o:odometer.cpp:(.text+0x168): first defined here
collect2: error: ld returned 1 exit status
makefile:2: recipe for target 'odometer' failed
make: *** [odometer] Error 1
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
CodyT96
  • 165
  • 1
  • 3
  • 12

4 Answers4

5

In short, replace #include "odometer.cpp" with #include "odometer.hpp". Now for the why.

Your program consists of source files like main.cpp and odometer.cpp. These files contain definitions for functions, variables, or classes in your project. Your compiler compiles each source file (.cpp) separately into object files (.o), and then your linker links these object files together to form your program.

However, although your source files are compiled separately, they will need to interact with each other. main.cpp will want to create Odometer objects and access Odometer member functions and so on. So we need a way to tell main.cpp what an Odometer is. The easiest way to do that is to define Odometer in a header file, and #include that header in main.cpp.

#include is a preprocessor directive that inserts the contents of another file into the current file. The preprocessor runs before your code is actually compiled. The idea is that you have some declarations in a file, which we call a header file, and multiple source files that need access to those declarations. So each source file will #include the header.

Note though that main.cpp doesn't need access to the definitions of Odometer's member functions, it just needs to know what those functions are and how to call them. That information is in the class definition in odometer.hpp, not in odometer.cpp. It would be an error to #include "odometer.cpp", because then we would have functions that are defined in two different places, and the linker will complain.

So in general you put your class definition in a header file (.hpp), put the class implementation in a source file (.cpp), and #include the header file in any other source file that needs access to that class. If you structure your programs correctly in this way, you should never need to #include a .cpp file into another .cpp file.

Greg Kikola
  • 573
  • 3
  • 6
1

The are multiple problems here:

odometer.hpp

  • Odometer(float g, int m): This is not defined in odometer.cpp
  • Odometer() : This default constructor should also be defined in odometer.cpp

  • Odometer has three member variables but only two are taken as input, it is unclear how the third mpg is initialized

  • There are no include guards in your header file

    #ifdef ODO_H

    #define ODO_H

    class Odometer{ // your class declaration };

    #endif

odometer.cpp

  • #include "odometer.hpp"

  • #include <iostream> - since you are using std::cout

  • Provide definitions for various Odometer constructors.

main.cpp

  • #include "odometer.hpp" - since you are using Odometer class here

Solving these issues should help you compile your code.

Rishi
  • 1,387
  • 10
  • 14
0

If you are including your odometer.cpp into your odometer_main.cpp, you can't also compile separately your odometer.cpp and link it with your odometer_main.cpp. In that case, yeah, you will get duplicate symbols. The typical way, though, is to only include the .hpp file into your main, and all else should compile and link fine.

Jim Buck
  • 20,482
  • 11
  • 57
  • 74
0

It is important to used file exclusion directives to avoid multiple inclusion.

#ifndef ODOMETER_H
#define ODOMETER_H
#include "odometer.h"
#endif

Have a look at this question:

Why are #ifndef and #define used in c++ header files

Also as the guys commented, you should include the h file

Community
  • 1
  • 1
Snake Sanders
  • 2,641
  • 2
  • 31
  • 42