|
From: Joacim Thomassen on 24 Jun 2008 16:54 Hi. I need some help with my understanding of code structures and scopes. g++ tells me that a namespace-global variable (ABC::a) either has "multiple definitions" or is "not used" if I change the type to static. Either way I don't understand why? 1. Why do I have to make it static? 2. If static is the answer why do g++ complain saying ABC::a "not used"? As I run the program ABC::a appears to be used with the correct and intended values. This program illustrates my problem: fil1.hpp #ifndef FIL1_HPP #define FIL1_HPP namespace ABC { bool a = 0; void set_a(bool val); bool get_a(); } #endif fil1.cpp #include "fil1.hpp" void ABC::set_a(bool val) { ABC::a = val; } bool ABC::get_a() { return ABC::a } fil2.hpp #ifndef FIL2_HPP #define FIL2_HPP class ClassA { public: ClassA(); }; class ClassB { public: bool g(); }; #endif fil2.cpp #include "fil2.hpp" #include "fil1.hpp" #include <iostream> ClassA::ClassA() { Abc::set_a(true); } int main(int argc, char *argv[]) { ClassB objB; std::cout << objB.g() << "\n"; ClassA objA; std::cout << objB.g() << "\n"; } fil3.cpp #include "fil2.hpp" #include "fil1.hpp" bool ClassB::g() { return Abc::get_a(); } Compiling the code gives this output from g++: g++ -o fil2 fil2.cpp fil3.cpp fil1.cpp /tmp/ccj0QGrI.o:(.bss+0x0): multiple definition of `ABC::a' /tmp/ccYUSmEL.o:(.bss+0x0): first defined here /tmp/cceKUTkJ.o:(.bss+0x0): multiple definition of `ABC::a' /tmp/ccYUSmEL.o:(.bss+0x0): first defined here collect2: ld returned 1 exit status make: *** [all] Error 1 The compiling and linking is successful as soon as I change the declaration in file1.hpp like this: - bool a = 0; + static bool a = 0; BUT 'g++ -Wall' gives this warning: g++ -Wall -o fil2 fil2.cpp fil3.cpp fil1.cpp fil1.hpp: At global scope: fil1.hpp:5: warning: 'ABC::a' defined but not used fil1.hpp:5: warning: 'ABC::a' defined but not used Why? This is disturbing as my program appears to do the right thing anyway. Running fil2 gives this stdout: 0 1 I know static will give the program only one occurrence of 'a' in memory. I don't understand why and how my program result in multiple definitions of ABC::a as I declar ABC::a non-static. The #ifndef check should protect me from multiple #includes messing things up? Is there something fundamental regarding namespace and scope I've missed? Please let me know what I'm looking for and where I can find some answers. Joacim Thomassen -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Thomas Richter on 24 Jun 2008 22:57 Joacim Thomassen schrieb: > Hi. > > I need some help with my understanding of code structures and > scopes. g++ > tells me that a namespace-global variable (ABC::a) either has > "multiple > definitions" or is "not used" if I change the type to static. Either > way > I don't understand why? You must only define it once, but you may declare it many times. > 1. Why do I have to make it static? I don't think you have to. > 2. If static is the answer why do g++ complain saying ABC::a "not > used"? Because there is a copy of ABC::a (actually multiple) that are not used. > As I run the program ABC::a appears to be used with the correct and > intended values. > > This program illustrates my problem: > > fil1.hpp > #ifndef FIL1_HPP > #define FIL1_HPP > namespace ABC { > bool a = 0; > void set_a(bool val); > bool get_a(); > } > #endif This breaks the one-definition-rule. If you include this file from multiple sources, ABC::a will be defined multiple times. Instead, declare it in the hpp file: namespace ABC { extern bool a; extern void set_a(bool val); extern bool get_a(); } and, within fil1.cpp, you define it by writing: namespace ABC { bool a = 0; } > I know static will give the program only one occurrence of 'a' in > memory. I afraid I believe wrong. "static" limits the visibility of a, but if you define a multiple times, you will have multiple copies of it. They do not conflict because the definition in one compilation unit is not visible in another. > I don't understand why and how my program result in multiple > definitions > of ABC::a as I declar ABC::a non-static. Because you define it multiple times. (-: > The #ifndef check should protect > me from multiple #includes messing things up? The define is not kept during multiple compiler runs. If you compile "file1.c" which includes fil1.hpp, and then run the compiler again on "file2.c", which also includes fil1.hpp, you'll have two definitions of ABC::a. So long, Thomas -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Thomas Maeder on 25 Jun 2008 08:56 Joacim Thomassen <joacim(a)olex.no> writes: > I need some help with my understanding of code structures and > scopes. g++ tells me that a namespace-global variable (ABC::a) > either has "multiple definitions" or is "not used" if I change the > type to static. Either way I don't understand why? fill.hpp contains a's definition; if fil1.hpp is #included by more than one translation unit (.cpp file) of a program, then that program contains multiple definitions. > 1. Why do I have to make it static? You don't. And normally you shouldn't. Declaring it static will cause each translation unit to have a separate variable a, unrelated to the as of the other translation units. NB: if you find this hard to read (I did when reading it through), then because a is a very clumsy variable name. :-) > 2. If static is the answer why do g++ complain saying ABC::a "not used"? > As I run the program ABC::a appears to be used with the correct and > intended values. No answer here, the premise isn't true. The real solution (from a language point of view; see below) is to declare (but not define) a in the header, and to define it in just one translation unit (the one that also defines set_a() and get_a()). > This program illustrates my problem: > > fil1.hpp > #ifndef FIL1_HPP > #define FIL1_HPP > namespace ABC { > bool a = 0; Change this to extern bool a; BTW: why didn't you use false to initialize a? > void set_a(bool val); > bool get_a(); > } > #endif > fil1.cpp > #include "fil1.hpp" Add namespace ABC { bool a = false; } here. > void ABC::set_a(bool val) { ABC::a = val; } > bool ABC::get_a() { return ABC::a } NB: no qualification of a is required in functions belonging to the same namespace. E.g.: void ABC::set_a(bool val) { a = val; } I wrote "from a language point of view" above, because from a design point of view, it's better to remove a from the header altogether. Anybody accessing a can use get_a() or set_a(), right? -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Martin T. on 25 Jun 2008 08:58 Joacim Thomassen wrote: > Hi. > > I need some help with my understanding of code structures and scopes. g++ > tells me that a namespace-global variable (ABC::a) either has "multiple > definitions" or is "not used" if I change the type to static. Either way > I don't understand why? > > 1. Why do I have to make it static? > 2. If static is the answer why do g++ complain saying ABC::a "not used"? > As I run the program ABC::a appears to be used with the correct and > intended values. > > This program illustrates my problem: > > fil1.hpp > #ifndef FIL1_HPP > #define FIL1_HPP > namespace ABC { > bool a = 0; > void set_a(bool val); > bool get_a(); > } > #endif > You are declaring two functions here but you are declaring _and_ defining the variable. If you only want to access the variable through your functions, the you should put the definition of the variable in the cpp file, i.e. change > fil1.cpp > #include "fil1.hpp" > void ABC::set_a(bool val) { ABC::a = val; } > bool ABC::get_a() { return ABC::a } > to fil1.cpp #include "fil1.hpp" namespace ABC { bool a = 0; void set_a(bool val) { a = val; } bool get_a() { return a } }; If you want the variable to be declared in the header, you have to use the 'extern' keyword. br, Martin -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Martin Bonner on 25 Jun 2008 08:57 On Jun 25, 8:54 am, Joacim Thomassen <joa...(a)olex.no> wrote: > Hi. > > I need some help with my understanding of code structures and scopes. g++ > tells me that a namespace-global variable (ABC::a) either has "multiple > definitions" or is "not used" if I change the type to static. Either way > I don't understand why? > > 1. Why do I have to make it static? > 2. If static is the answer why do g++ complain saying ABC::a "not used"? > As I run the program ABC::a appears to be used with the correct and > intended values. > > This program illustrates my problem: I have shrunk the code: > > fil1.hpp > #ifndef FIL1_HPP > #define FIL1_HPP > namespace ABC { > bool a = 0; > } > > #endif > > fil1.cpp > #include "fil1.hpp" ... use ABC::a > fil2.cpp > #include "fil1.hpp" ... also use ABC::a The problem is that fil1.hpp DEFINES ABC::a. You need to make sure that it only DECLARES it. Change the header file to: extern bool a; (which is just a declaration). And then, in file1.hpp, add the following line to define the variable: bool ABC::a = false; That will fix everything. > I know static will give the program only one occurrence of 'a' in memory. No, no, no! If you put "static" in the header file, there will be *three* separate occurences of 'a' - one for each of the files where you #include "fil1.hpp". That is why gcc complains. In fil2.cpp and fil3.cpp you don't use the copy you have added. In fact, in this /particular/ case, the correct thing to do, is to remove the declaration of 'a' from the header file completely (it is only used in fil1.cpp, and nobody else needs it). You can then declare (and define) it as static in fil1.cpp (or put it in the unnamed namespace). Note: Your current code (with static) will work; you just waste some space. But as soon as you make get_a inline, it will stop working! > I don't understand why and how my program result in multiple definitions > of ABC::a as I declar ABC::a non-static. The #ifndef check should protect > me from multiple #includes messing things up? Is there something > fundamental regarding namespace and scope I've missed? Please let me know > what I'm looking for and where I can find some answers. { Signature and clc++m banner removed; please, please, don't quote them, as you're not replying to them. -mod } -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
|
Next
|
Last
Pages: 1 2 3 Prev: Division result is always 100 instead of 99.99 Next: 64-bit Random Number Generator |