(simple) header file problem

M

michael

Hi All,

I have the following:

------------ file constants.h---------
#ifndef constants_
#define constants_

const int FOO = 1;
const int BAR = 2;
char* NAME = "something";
const int ARGCOUNT = 2;

#endif

----------- file other.h -------------
#ifndef other_
#define other_

#include "Constants.h"

class Other {
public:
void crap();
};

#endif

----------- file other.cpp ----------
#include "Other.h"

void Other::crap(){
//stuff to do stuff
}
---------- file crap.cpp -----------
#include <iostream>
#include "constants.h"
#include "other.h"

using namespace std;

void doStuff(char* arg){
cout << "arg was " << arg << endl;
}

int main(int argc, char* argv[]){
if(argc < ARGCOUNT)
doStuff(NAME);
else
doStuff(argv[1]);
}
------------------------------------

When I compile, the compiler complains that I have 'multiple definition of
_NAME'
It has no problem with the other variables I have defined in Constants.h, so
why the problem with NAME?

It seems to be something to do with the char*, but I can't figure out what
or why.....

Thanks for your help

Michael
 
I

Ian Collins

michael said:
Hi All,

I have the following:

------------ file constants.h---------
#ifndef constants_
#define constants_

const int FOO = 1;
const int BAR = 2;
char* NAME = "something";
const int ARGCOUNT = 2;

#endif


When I compile, the compiler complains that I have 'multiple definition of
_NAME'
It has no problem with the other variables I have defined in Constants.h, so
why the problem with NAME?
The others are constants, why isn't NAME?
 
M

MIUSS

Don't you have one of cpp file as part as the other one? I ain't
expert but I suppose that the multiple definition of _NAME is because
the compiler gets that definition more times. It could be due the
including the header file "constants.h" from both (other.cpp,
crap.cpp) files...

michael napsal:
 
I

Ian Collins

MIUSS said:
Don't you have one of cpp file as part as the other one? I ain't
expert but I suppose that the multiple definition of _NAME is because
the compiler gets that definition more times. It could be due the
including the header file "constants.h" from both (other.cpp,
crap.cpp) files...
Please don't top post.
michael napsal:
Hi All,

I have the following:

------------ file constants.h---------
#ifndef constants_
#define constants_

const int FOO = 1;
const int BAR = 2;
char* NAME = "something";
const int ARGCOUNT = 2;

#endif

----------- file other.h -------------
#ifndef other_
#define other_

#include "Constants.h"

class Other {
public:
void crap();
};

#endif

----------- file other.cpp ----------
#include "Other.h"

void Other::crap(){
//stuff to do stuff
}
---------- file crap.cpp -----------
#include <iostream>
#include "constants.h"
#include "other.h"

using namespace std;

void doStuff(char* arg){
cout << "arg was " << arg << endl;
}

int main(int argc, char* argv[]){
if(argc < ARGCOUNT)
doStuff(NAME);
else
doStuff(argv[1]);
}
------------------------------------

When I compile, the compiler complains that I have 'multiple definition of
_NAME'
It has no problem with the other variables I have defined in Constants.h, so
why the problem with NAME?

It seems to be something to do with the char*, but I can't figure out what
or why.....

Thanks for your help

Michael
 
N

nishit.gupta

MIUSS said:
Don't you have one of cpp file as part as the other one? I ain't
expert but I suppose that the multiple definition of _NAME is because
the compiler gets that definition more times. It could be due the
including the header file "constants.h" from both (other.cpp,
crap.cpp) files...

michael napsal:
Hi All,

I have the following:

------------ file constants.h---------
#ifndef constants_
#define constants_

const int FOO = 1;
const int BAR = 2;
char* NAME = "something";
const int ARGCOUNT = 2;

#endif

----------- file other.h -------------
#ifndef other_
#define other_

#include "Constants.h"

class Other {
public:
void crap();
};

#endif

----------- file other.cpp ----------
#include "Other.h"

void Other::crap(){
//stuff to do stuff
}
---------- file crap.cpp -----------
#include <iostream>
#include "constants.h"
#include "other.h"

using namespace std;

void doStuff(char* arg){
cout << "arg was " << arg << endl;
}

int main(int argc, char* argv[]){
if(argc < ARGCOUNT)
doStuff(NAME);
else
doStuff(argv[1]);
}
------------------------------------

When I compile, the compiler complains that I have 'multiple definition of
_NAME'
It has no problem with the other variables I have defined in Constants.h, so
why the problem with NAME?

It seems to be something to do with the char*, but I can't figure out what
or why.....

Thanks for your help

Michael

First : Not the compiler, rather linker will complaint for multiple
definitation for NAME. As at compile
multiple definitions you have avoided through #ifndef ..statements but
at link time these files migth be
included in other files so multiple definition found
SECOND: All other variables you have declared as const except name. In
c++ const has internal linkage so
const variables will not be detected by linker but NAME has external
linkage so linker may find multiple definition
of NAME (if included in multiple files)
 
G

Greg Comeau

The others are constants, why isn't NAME?

As well, if it doesn't need to be a pointer, [] it.

As to your original question: It would be multiply defined everywhere.
The consts in this case escape that because they are int's,
however, the pointer (or even in the [] case) will be laid
down every time you #include the constants.h file.
So you probably want to define it once (in a non-header file)
and extern it everywhere else (that is, in the header file).
There are some other macros you can establish to automate it
if used across many such objects, and how to do that is
probably in the FAQ (or the C FAQ).
 
G

Greg Comeau

MIUSS said:
Don't you have one of cpp file as part as the other one? I ain't
expert but I suppose that the multiple definition of _NAME is because
the compiler gets that definition more times. It could be due the
including the header file "constants.h" from both (other.cpp,
crap.cpp) files...

michael napsal:
------------ file constants.h---------
#ifndef constants_
#define constants_

const int FOO = 1;
const int BAR = 2;
char* NAME = "something";
const int ARGCOUNT = 2;

#endif

----------- file other.h -------------
#ifndef other_
#define other_

#include "Constants.h"

class Other {
public:
void crap();
};

#endif

----------- file other.cpp ----------
#include "Other.h"

void Other::crap(){
//stuff to do stuff
}
---------- file crap.cpp -----------
#include <iostream>
#include "constants.h"
#include "other.h"

using namespace std;

void doStuff(char* arg){
cout << "arg was " << arg << endl;
}

int main(int argc, char* argv[]){
if(argc < ARGCOUNT)
doStuff(NAME);
else
doStuff(argv[1]);
}
------------------------------------

When I compile, the compiler complains that I have 'multiple definition of
_NAME'
It has no problem with the other variables I have defined in Constants.h, so
why the problem with NAME?

It seems to be something to do with the char*, but I can't figure out what
or why.....

Thanks for your help

Michael

First : Not the compiler, rather linker will complaint for multiple
definitation for NAME. As at compile
multiple definitions you have avoided through #ifndef ..statements but
at link time these files migth be
included in other files so multiple definition found
SECOND: All other variables you have declared as const except name. In
c++ const has internal linkage so
const variables will not be detected by linker but NAME has external
linkage so linker may find multiple definition
of NAME (if included in multiple files)

True, but generally, laying down a copy of NAME, and perhaps
the literal too, in every translation unit is probably not the best
solution.
 
M

michael

Ian Collins said:
The others are constants, why isn't NAME?
I originally had is as a const, but I got other errors and while trying to
work them out I changed it to just char*

What I'm trying to achieve is simple use of the command line arguments, with
a default if no argument is entered:

const char* DEFAULT_FILENAME = "somefilename";
const int ARGS = 2;

int main(int argc, char* argv[]){
if(argc < ARGS)
doStuff(DEFAULT_FILENAME);
//doStuff("somefilename");
else
doStuff(argv[1]);
}


void doStuff(char* name){
}

If I do it like above I get 'no matching function call doStuff(const char*)
near match is doStuff(char*) ' errors.
Surely I dont need to have a separate function?
 
I

Ian Collins

michael said:
I originally had is as a const, but I got other errors and while trying to
work them out I changed it to just char*

What I'm trying to achieve is simple use of the command line arguments, with
a default if no argument is entered:

const char* DEFAULT_FILENAME = "somefilename";

Make this const char* const DEFAULT_FILENAME = "somefilename";

Note the second const, this declares the pointer to be a constant. This
will remove your duplicate definition problem. I'd avoid all caps here
as they make the name look like a macro.
const int ARGS = 2;

int main(int argc, char* argv[]){
if(argc < ARGS)
doStuff(DEFAULT_FILENAME);
//doStuff("somefilename");
else
doStuff(argv[1]);
}


void doStuff(char* name){

Make this void doStuff( const char* name) {

If your default is a string literal, you can't modify the value passed,
so the parameter should be const char*.
 
I

Ian Collins

Ian said:
Make this const char* const DEFAULT_FILENAME = "somefilename";

Note the second const, this declares the pointer to be a constant. This
will remove your duplicate definition problem.

I should have added the caveat that this will add the literal to each
object file, so a better approach is to use extern and define the
constant in one source file.
 
M

michael

Ian Collins said:
michael said:
I originally had is as a const, but I got other errors and while trying to
work them out I changed it to just char*

What I'm trying to achieve is simple use of the command line arguments, with
a default if no argument is entered:

const char* DEFAULT_FILENAME = "somefilename";

Make this const char* const DEFAULT_FILENAME = "somefilename";

Note the second const, this declares the pointer to be a constant. This
will remove your duplicate definition problem. I'd avoid all caps here
as they make the name look like a macro.
const int ARGS = 2;

int main(int argc, char* argv[]){
if(argc < ARGS)
doStuff(DEFAULT_FILENAME);
//doStuff("somefilename");
else
doStuff(argv[1]);
}


void doStuff(char* name){

Make this void doStuff( const char* name) {

If your default is a string literal, you can't modify the value passed,
so the parameter should be const char*.

Thanks for that. Now I better go and read up on the use of const so I
understand what I'm doing :)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,014
Latest member
BiancaFix3

Latest Threads

Top