LinuxQuestions.org
Latest LQ Deal: Latest LQ Deals
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 05-15-2005, 01:13 AM   #1
kevin_cpp
LQ Newbie
 
Registered: May 2005
Posts: 4

Rep: Reputation: 0
Simple C++ Namespace Question


Hi all,

I'm trying to use the "namespace" feature of C++ but I'm getting linker errors. It seems like the fix should be trivial but I don't know how to do it.
Here's what I'm doing:

-------- Main File --------------------
#include (the standard stuff)

#include "inner_file.h"
#include "outer_file.h"

int main()
{
inner::f();
...
outer::f();
}
-------- inner_file.h ------------
namespace inner
{
int A[10];
void f();
}
-------- inner_file.cpp ----------
#include "inner_file.h"
namespace inner
{
void f() { /* implementation */ }
}

Then I also have "outer_file.h" and "outer_file.cpp" but they're the same as the inner_files with the exception that the namespace is now "outer". When I compile it, I get a linker error saying that

inner::A already exists

(or something along those lines)

What am I doing wrong?

Thanks,

Kevin
 
Old 05-15-2005, 06:19 AM   #2
Hivemind
Member
 
Registered: Sep 2004
Posts: 273

Rep: Reputation: 30
Post the smallest possible example condensed to a single file along with the error message you received
and the compiler options you used.
 
Old 05-15-2005, 07:05 AM   #3
YetAnotherDave
Member
 
Registered: Feb 2005
Posts: 95

Rep: Reputation: 17
This is not a namespace related problem. The problem is that you are defining array "A" in an include file ( inner_file.h ) and then including that file in two c++ files. This causes the multiple definition.

To fix, change the "A" definition to a declaration by placing "extern" in front of it and define "A" one time in a c++ file ( inner_file.cpp seems like the sensible choice). This should take care of the "already exists" error.

- Dave
 
Old 05-15-2005, 07:12 AM   #4
Hivemind
Member
 
Registered: Sep 2004
Posts: 273

Rep: Reputation: 30
Of course, I skimmed the post too quickly.
 
Old 05-15-2005, 09:20 PM   #5
kevin_cpp
LQ Newbie
 
Registered: May 2005
Posts: 4

Original Poster
Rep: Reputation: 0
Thanks a lot Dave. I figured something like that was up. Before reading your reply, I was able to get it to compile and link when I added

#pragma once

to all my header files AND I had to declare the array A to be static in both header files. Things seemed to work fine, but I don't really like my fix. Are there any potential downfalls of doing things this way?

Anyways, I'll go ahead and modify the header file declaration to an extern and actually define it in my cpp file.

Thanks a lot for your help.

Kevin
 
Old 05-16-2005, 05:09 AM   #6
YetAnotherDave
Member
 
Registered: Feb 2005
Posts: 95

Rep: Reputation: 17
I think the technique you described ( "pragma once" & static declarations ) would have gotten a clean compile and link even without the "pragma once". Just making the declarations static would be enough for a clean compile & link.

The downfall is that this does *not* give you the same meaning as extern declaration in include file with definition in cpp file. If the array definition is static then each compilation that includes this definition results in an independently defined "A" array. Changes made in the "A" array in one cpp file will have nothing to do with changes made in another cpp file.

- Dave
 
Old 05-16-2005, 05:38 AM   #7
jtshaw
Senior Member
 
Registered: Nov 2000
Location: Seattle, WA USA
Distribution: Ubuntu @ Home, RHEL @ Work
Posts: 3,892
Blog Entries: 1

Rep: Reputation: 67
I know you are already fixed and on your merry way... however I thought I give my 2 cents.


You'll notice the following alot in header files:
Code:
#ifndef HEADERFILENAME_H
#define HEADERFILENAME_H
<insert the meat and potatoes of your header here>
#endif
This ensures that your header file will be safe when linked into a large project where multiple objects might be including it that later get linked together. I pretty much consider it standard practice to declare headers in this way and you'll notice many others use this method as well.
 
Old 05-16-2005, 06:00 PM   #8
kevin_cpp
LQ Newbie
 
Registered: May 2005
Posts: 4

Original Poster
Rep: Reputation: 0
Thanks "jtshaw" for your tip on the macro guard. Thank you Dave for explaining the downfall of static, but I'm afraid I'm still a bit confused.

What do you mean by:

Quote:
"each compilation that includes this definition results in an independently defined "A" array"
I thought static meant that there should be only one. So let me see if I understand you correctly:

Let "f1.cpp" and "f2.cpp" be two source files that include "header.h" ("header.h" contains a static array A[10]). Let "main.cpp" be the main program. Now if I do this:

g++ -c main.cpp
g++ -c f1.cpp
g++ -c f2.cpp
g++ f1.o f2.o main.o -o exe

Are you saying that functions within f1.cpp will be using an "A" that is different than the "A" that f2.cpp sees?

Thanks again for everyone's help,

Kevin
 
Old 05-16-2005, 07:09 PM   #9
YetAnotherDave
Member
 
Registered: Feb 2005
Posts: 95

Rep: Reputation: 17
Quote:
Let "f1.cpp" and "f2.cpp" be two source files that include "header.h" ("header.h" contains a static array A[10]). Let "main.cpp" be the main program. Now if I do this:

g++ -c main.cpp
g++ -c f1.cpp
g++ -c f2.cpp
g++ f1.o f2.o main.o -o exe

Are you saying that functions within f1.cpp will be using an "A" that is different than the "A" that f2.cpp sees?
Yes, that's right. Here's a demo of exactly that scenario:


main.cpp
Code:
void initA1();
void showA1();

void initA2();
void showA2();

int main()
{
    initA1();
    initA2();
    showA1();
    showA2();
}

header.h
Code:
#ifndef HEADER_H__
#define HEADER_H__
#define COUNT 2
static int A[COUNT];
#endif // HEADER_H__

f1.cpp
Code:
#include "header.h"
#include <iostream>

using namespace std;

void initA1()
{
   for (int i = 0; i < COUNT; ++i)
   {
       A[i] = 1;
   }
}

void showA1()
{
   cout << "f1.cpp: A Array:" << endl;
   for (int i = 0; i < COUNT; ++i)
   {
       cout << "A[" << i << "] = " << A[i] << endl;
   }
   cout << endl;
}
f2.cpp
Code:
#include "header.h"
#include <iostream>

using namespace std;

void initA2()
{
   for (int i = 0; i < COUNT; ++i)
   {
       A[i] = 2;
   }
}

void showA2()
{
   cout << "f2.cpp: A Array:" << endl;
   for (int i = 0; i < COUNT; ++i)
   {
       cout << "A[" << i << "] = " << A[i] << endl;
   }
   cout << endl;
}
The main() routine calls initA1() and initA2() . If the arrays were the same, the second init would overwrite the results of the first. However, as the calls to showA1() and showA2() demonstrate, the arrays are distinct. Here are the compile and output results:

Quote:
dave@ruby:~/ctest2$ make
g++ -c -o main.o main.cpp
g++ -c -o f1.o f1.cpp
g++ -c -o f2.o f2.cpp
g++ main.o f1.o f2.o -o exe
dave@ruby:~/ctest2$ ./exe
f1.cpp: A Array:
A[0] = 1
A[1] = 1

f2.cpp: A Array:
A[0] = 2
A[1] = 2


The static definition means that the scope ( i.e. visibility ) is limited to "only one" object file. This is what permits different definitions in different object files.

- Dave
 
Old 05-17-2005, 04:19 PM   #10
kevin_cpp
LQ Newbie
 
Registered: May 2005
Posts: 4

Original Poster
Rep: Reputation: 0
Thanks Dave again for all your help. That example clears things up. I thought static applied to the scope of the entire program. So here's a related question:

Suppose I had a class (SomeClass) and I define a static member variable called (SomeClass.instanceN) and increment this by one each time an instance is created. Then, does this mean that I cannot count on this variable to give the true number of instances across multiple CPP files... How would one keep track of the number of instances then?

Kevin
 
Old 05-17-2005, 04:32 PM   #11
Hivemind
Member
 
Registered: Sep 2004
Posts: 273

Rep: Reputation: 30
A static data member in a class retains the same value for all objects of the class at any given time, regardless
of what translation unit the object itself was created. When a program is running, it has no concept of source
files.
 
Old 05-17-2005, 05:31 PM   #12
YetAnotherDave
Member
 
Registered: Feb 2005
Posts: 95

Rep: Reputation: 17
Quote:
A static data member in a class retains the same value for all objects of the class at any given time, regardless
of what translation unit the object itself was created. When a program is running, it has no concept of source
files.
That's right. The static modifier has a different meaning for class member variables than it does for variables that are defined outside of any particular scope. I remember this being counter intuitive when I first learned c++ but you get used to it pretty fast.

- Dave

Last edited by YetAnotherDave; 05-17-2005 at 05:36 PM.
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
Ubuntu Fluxbox simple question, simple answer? generallimptoes Linux - Software 3 09-26-2005 02:03 PM
Installing Programs - A simple question from my simple mind jmp875 Linux - Newbie 6 02-18-2004 09:03 PM
Understanding Namespace? nny0000 Programming 2 12-22-2003 08:45 PM
namespace? using? explicit? restrict? what are these? Hano Programming 3 04-11-2002 07:02 AM
simple question seeking simple answer enzo250gto Linux - Newbie 1 10-27-2001 04:08 AM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 07:48 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration