2

I am trying to learn the C++ language (so kindly bear with my noobness). On following the tutorial in several books I decided to experiment with headers

I have a file named Untitled2.cpp which contains

#include <iostream>
#include "findaverage.h"
#include <string>
using namespace std;

int main(){
cout<<find_average();
}

A header file named findaverage.h which contain

#ifndef FINDAVERAGE_H
#define FINDAVERAGE_H
int find_average();
double first_no;
double second_no;
#endif

and a findaverage.cpp file which contain

#include "findaverage.h"
#include <iostream>
using namespace std;
int find_average(){
std::cout << "Enter a number"<<endl;
std::cin>>first_no;
std::cout<<"Enter another number"<<endl;
std::cin>>second_no;
return (first_no+second_no)/2;
};

when i compile the program in Code::Blocks, I get the following error

||=== Build: Debug in test (compiler: GNU GCC Compiler) ===|
obj/Debug/Untitled2.o||In function `main':|
/root/Untitled2.cpp|7|multiple definition of `second_no'|
obj/Debug/findaverage.o:/root/findaverage.cpp|5|first defined here|
||error: ld returned 1 exit status|
||=== Build failed: 3 error(s), 0 warning(s) (0 minute(s), 0 second(s)) ===|

I am trying to follow the an approach similar to this picture

enter image description here

Question: how can I successfully resolve the multiple definition issue in my experimental code?

Matteo Italia
  • 123,740
  • 17
  • 206
  • 299
repzero
  • 8,254
  • 2
  • 18
  • 40
  • 1. Not a good idea to use [using namespace std;](http://stackoverflow.com/questions/1452721/why-is-using-namespace-std-in-c-considered-bad-practice) 2. Please do not post images unless yo have to – Ed Heal Jun 06 '16 at 00:01
  • 1
    Why is `double first_no; double second_no;` in a header file – Ed Heal Jun 06 '16 at 00:02
  • 1
    I guess you are trying to use global variables - this is also a bad idea – Ed Heal Jun 06 '16 at 00:03
  • @Ed Heal..I am of the opinion that we can put it in a header? I am looking at the snap from the picture and experiment...I can't say where I am going wrong though. – repzero Jun 06 '16 at 00:04
  • 1
    Do not use global variables. Put them into the .cpp file and inside the function – Ed Heal Jun 06 '16 at 00:05

2 Answers2

4

The problem is that you include a header with definition of your global variables. Headers should include only declarations, not definitions:

#ifndef FINDAVERAGE_H
#define FINDAVERAGE_H
int find_average();
extern double first_no;
extern double second_no;
#endif

This would fail to build with a different error, however, because you need to provide definitions for your variables in one of your cpp files - for example, in Untitled2.cpp:

#include <iostream>
#include "findaverage.h"
#include <string>
using namespace std;

int main(){
    cout<<find_average();
}

double first_no;
double second_no;

Note that if you do not need these variables to be global, you could make them local to your function, or local to your cpp file.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • This appears to solve the issue but I am getting another error "undefined reference to first_no" in findaverage.cpp – repzero Jun 06 '16 at 00:07
  • @repzero Did you add definitions to your `Untitled2.cpp` as shown above? – Sergey Kalinichenko Jun 06 '16 at 00:09
  • Excellent!!!!.....I think I get the picture now...I'll need to read up some more on extern...I noticed it but never grasp it mentally... – repzero Jun 06 '16 at 00:19
  • 1
    @repzero The deal with extern is pretty simple. I think you already see what's going on with functions vs prototypes - i.e. the header has the declaration without a body, which makes it a declaration, while the cpp has the header again plus the body, which makes it a definition. Variables don't have "body" either way, so `extern` says "this is a variable with no body", i.e. a promise to have a variable by the same name elsewhere. The same variable declared in cpp file provides the "body", so that he linker can find it. – Sergey Kalinichenko Jun 06 '16 at 00:23
  • ..thanks for breaking this down to the ground for me..:D – repzero Jun 06 '16 at 00:26
3

Change the header file to

#ifndef FINDAVERAGE_H
#define FINDAVERAGE_H
int find_average();
// No - wrong place double first_no;
// No - wrong place double second_no;
#endif

as the variables will be included where ever the header file is in a .cpp file

and change the function to this

int find_average(){
  double first_no;
  double second_no;

   std::cout << "Enter a number"<<endl;
   std::cin>>first_no;
   std::cout<<"Enter another number"<<endl;
   std::cin>>second_no;
   return (first_no+second_no)/2;
};

Should add error checking in case the user does not enter a number - but I leave that to the reader

Ed Heal
  • 59,252
  • 17
  • 87
  • 127