C++: life-cycle of variables in namespaces - c++

Can someone please explain to me the life cycle of a variable from a namespace? Let's say I have the following files:
file.h:
// ...
namespace variables{
int x, y;
}
file.cpp:
#include "file.h"
using namespace variables;
int main(){
...
}
What are the scopes of x and y? I ask because, in a book I was reading (C++ Primer Plus), the author recommends using namespaces inside functions, and so I thought that they are defined at the point of the using command. However, when I do this:
B.h:
class B{
// class stuff
};
namespace variables{
int x, y;
}
and then in main.cpp (main program) and B.cpp (class implementation) I add the #include "B.h" line, I get an error that I have multiple definitions of variables::x and variables::y, even though there is no using in any file. What's the deal? Am I mixing up two different concepts?

If you directly declare variables in a namespace just like you did, they will simply exist as global variables.
Thus, the rules that apply for normal global variables also apply for those ones : they will exist for as long as the program run, and you should not define them in a header file.
include.h
namespace Variables
{
extern int x;
extern int y;
}
file.cpp
namespace Variables
{
int x;
int y;
}
Writing using namespace Variables will simply allow you to access those variables by their name x and y, without having to prefix them with Variables::

Namespace has no influence on variable's lifespan, so:
namespace variables{
int x, y;
}
#include "file.h"
using namespace variables;
int main(){
...
}
What are the scopes of x and y?
These variables are global, so their life time equals to life time of the entire application.
Remember, that using namespace is simply a shortcut to writing NamespaceName:: in front of elements from this namespace.

I add the #include "B.h" line, I get an error that I have multiple definitions of variables::x and variables::y, even though there is no using in any file. What's the deal? Am I mixing up two different concepts?
Your variables are declared even if you do not explicitly import the namespace. The keyword using import namespaces or specific names within the current scope so that you don't have to prepend X:: to access a defined element.
The life span of a variable is not affected by namespaces.

Related

Static variables and different namespaces in c++

I have read on static variables and know what they are, how they function when define in a .cpp file, function, and class.
But I have slight confusion when define in different namespaces in the same cpp file.
One of these voted answers here says:
When you declare a variable as static inside a .h file (within or without namespace; doesn't matter), and include that header file in various .cpp files, the static variable becomes locally scoped to each of the .cpp files.
According to the program below, namespaces does matter.
static int a = 0;
namespace hello1 {
static int a = 1;
namespace hello2 { static int a = 2;}
namespace hello3 { static int a = 3;}
}
int main()
{
std::cout<<::a<<hello1::a<<hello1::hello2::a<<hello1::hello3::a;
return 0;
}
output
0123
Here is what I think: a outside namespaces is the file scope. a in hello1 is hello1 scope. Since hello1 is global scope namespace, I can only have one a in namespace hello1, including other cpp files where hello1 exists. The same goes for hello2 and hello3; only one a in each hello1::hello2 and hello1::hello3.
Please correct me If I understood it correct. The namespace does matter; static variables in the same cpp file under different namespaces are different entities.
That's not what the passage you quoted is talking about. It is referring to the fact that static variable names have internal-linkage. What that means is that you can't access a static variable a that is defined in "a.cpp" from "b.cpp", even if you include a declaration of a in "b.cpp". That declaration will refer to a different object.
For example:
A.hpp
static int a = 0;
void foo();
A.cpp
#include "A.hpp"
#include <iostream>
void foo() { std::cout << a << '\n'; }
B.cpp
#include "A.hpp"
#include <iostream>
int main() {
std::cout << a << '\n'; // prints 0
a = 1;
foo(); // prints 0, since it uses a different a
}
In this example, "A.cpp" and "B.cpp" see different global-scope objects named a since a was declared static. Even though main modifies a's value to be 1, foo still sees it as 0 since it's looking at a different a.
This behavior is irrespective of namespaces. If a were in a namespace other than the global namespace this same behavior would occur. That is what the passage you quoted is referring to.

C++ Problems with splitting code into multiple files

So, I am working on a project and decided to split the code into multiple files as it was getting too big. However, a got a compilation error. I managed to recreate the error in this simple case:
//main.cpp
#include<iostream>
#include "classa.h"
using namespace std;
int main()
{
return 0;
}
The main does nothing it just includes classa.h
//classa.h
#ifndef CLASSA_H_INCLUDED
#define CLASSA_H_INCLUDED
#include<vector>
using namespace std;
vector<int> primes= {1,2,3,5,7,11,13,17,19};
class classa
{
private:
int a;
public:
int getA();
void setA(int newA);
};
#endif //CLASSA_H_INCLUDED
The class isn't even necessary for the error to occur. However, I wanted to have something in classa.cpp
//classa.cpp
#include "classa.h"
using namespace std;
int classa::getA()
{
return a;
}
void classa::setA(int newA)
{
a=newA;
}
It gives me the following error:
obj\Debug\sources\main.o:main.cpp:(.bss+0x0): multiple definition of `primes'
obj\Debug\sources\classa.o:classa.cpp:(.bss+0x0): first defined here
The problem is that unlike here in my project I cannot use some sort of constant or a define for the global variables as they are things that can be modified by different classes.
Make primes an extern variable, and declare it in your classa.h header, but only defined it once in classa.cpp.
Currently, as your compiler told you, primes exists twice, in main.cpp and in classa.cpp. Keep in mind, #include is merely text substitution.
classa.h:
extern std::vector<int> const primes;
classa.cpp:
std::vector<int> const primes = {1,2,3,5,7,11,13,17,19};
Read more about storage class specifiers here.
If you have .cpp file in overall - then it makes sense to split into
Into .h file:
extern std::vector<int> primes;
Into .cpp file:
using namespace std;
vector<int> const primes = {1,2,3,5,7,11,13,17,19};
"using namespace std" might cause conflicts between 3rd party libraries, but this occurs very rarely - I prefer to use "using namespace std" whenever possible. But if there are conflicts - then you might want to localized "using namespace std" into your own .cpp file. (Where you control what #include's that file has).
But sometimes you might not have .cpp file at all (e.g. only local inline functions or template classes) - then you can initialize vector like this:
__declspec(selectany) std::vector<int> primes = {1,2,3,5,7,11,13,17,19};
This will instruct linker to pick up only one copy (some of them), and discard everything else. This does not play well if you want to #ifdef some of initialization, but this is not normal use case anyway.
I prefer not to use const ever, because it's always pain in neck to get const right after 2-3 level conversions. I write in function comments what is input / what is output and what should not be modified. (Because that one can change over iterations)

Is there a way to define functions declared in a namespace in a separate .h and .cpp file?

I am still kind of new to many areas of c++ and one is general .cpp and .h file organization.
I am creating a namespace with some structs and functions. I would like to declare the namespace in a .h file similar to this
//objectname.h
namespace ObjectName
{
Object Function(arguments);
}
declarations in function.h
//function.h
//includes declarations used in the function definition as well
//as possibly a redundant function declaration.
Object Function(arguments);
then the definition in function.cpp
//function.cpp
#include "Function.h"
Object Function(arguments)
{
....
}
So that you can see abstractly the namespace in objectname.h, function particular declarations in function.h and function definition in function.cpp. As always any suggestions are greatly appreciated. (also windows based c++)
This is fine
//objectname.h
namespace ObjectName
{
Object Function(arguments);
}
You don't need function.h at all. If you want to split the namespace into several files, you would do it like:
//function.h
//includes declarations used in the function definition as well
//as possibly a redundant function declaration.
namespace ObjectName
{
Object Function(arguments);
}
In other words you need to wrap the declaration in the namespace again. (This is an advance topic. I wouldn't do it.)
Function.cpp just needs to say which function it is defining:
//function.cpp
#include "ObjectName.h"
Object ObjectName::Function(arguments)
{
....
}
Note that the statement to use a header file is #include, not using
That's not how it works: your function.h defines another Function in the global namespace. Having two functions with the same name is exactly what namespaces are for - a library write doesn't need to worry if there's already a Function in any other library.
And as your .cpp defines only one of the two Functions, the other one is undefined and will give a link error when called.
Note that you do not need to "define" a namespace all at once. Take for instance namespace std, whose contents are found in e.g. <vector>, <list> and <iostream>. This is possible because unlike a class, a namespace can be reopened. namespace N { int x; } namespace N { int y; } is valid.

namespace-name not recognized

I have the following two sample c++ files:
File: foo.cc
namespace test_ns {
int x = 100;
}
File: bar.cc
using namespace test_ns;
extern int x;
int main()
{
x = 200;
return 0;
}
I must be doing something really silly as I am getting the following compiler error:
bar.cc:2:17: error: 'test_ns' is not a namespace-name
bar.cc:2:24: error: expected namespace-name before ';' token
However, my main question (after I resolve the namespace error), with the code as is, should I be able to use "x" in bar.cc, or do I need to use additional qualifiers.
Sorry to bother with such a simple issue, but I am pretty stumped with such a simple program.
Thank you,
Ahmed.
Just like every other name in C++, a namespace name must be declared before it can be accessed. When compiling bar.cc, the compiler doesn't know test_ns is a namespace name - you haven't provided a declaration for it.
Namespaces and using namespace aren't magical tricks that let you get around the necessity to declare anything you want to use. To make this work, create a header file:
foo.hh
namespace test_ns {
extern int x;
}
Then #include "foo.hh" in bar.cc, and remove extern int x; from bar.cc. That will make these two translation units form a valid program. And after you do that, referring to x in bar.cc will indeed refer to test_ns::x (thanks to the using directive).
As a side note, if you don't remove the extern int x; from bar.cc (after you include the header file), it will declare a new global variable ::x and not refer to test_nest::x. using namespace in a source file allows you to define class members without referring to the class's namespace, but namespace-scope entities (variables and functions) always have to be defined inside the namespace or using a qualified name.
They are in different compilation units. You need to declare the namespace in a common header; which you can do using:
namespace test_ns {}
namespace is defined in a different file. It needs to be defined in a header file which should be included in bar.cc .

C++: Namespaces -- How to use in header and source files correctly?

Consider a pair of two source files: an interface declaration file (*.h or *.hpp) and its implementation file (*.cpp).
Let the *.h file be like the following:
namespace MyNamespace {
class MyClass {
public:
int foo();
};
}
I have seen two different practices for using namespaces in source files:
*.cpp showing practice #1:
#include "MyClass.h"
using namespace MyNamespace;
int MyClass::foo() { ... }
*.cpp showing practice #2:
#include "MyClass.h"
namespace MyNamespace {
int MyClass::foo() { ... }
}
My question: Are there any differences between these two practices and is one considered better than the other?
From a code readability standpoint, it is probably better in my opinion to use the #2 method for this reason:
You can be using multiple namespaces at a time, and any object or function written below that line can belong to any of those namespaces (barring naming conflicts). Wrapping the whole file in a namespace block is more explicit, and allows you to declare new functions and variables that belong to that namespace within the .cpp file as well
The clearest is the option you didn't show:
int MyNamespace::MyClass::foo()
{
// ...
}
It's also very verbose; too much so for most people. Since using namespace is a recipe for name conflicts, at least in my experience,
and should be avoided except in very limited scopes and places, I
generally use your #2.
Are there any differences between these two practices
Yes. #1 and #2 are examples of a using-directive and a namespace definition respectively. They are effectively the same in this case but have other consequences. For instance, if you introduce a new identifier alongside MyClass::foo, it will have a different scope:
#1:
using namespace MyNamespace;
int x; // defines ::x
#2:
namespace MyNamespace {
int x; // defines MyNamespace::x
}
is one considered better than the other?
#1 Pros: a little more terse; harder to accidentally introduce something into MyNamespace unwittingly. Cons: may pull in existing identifiers unintentionally.
#2 Pros: more clear that definitions of existing identifiers and declarations of new identifiers both belong to MyNamespace. Cons: easier to unintentionally introduce identifiers to MyNamespace.
A criticism of both #1 and #2 is that they are referring to an entire namespace when you probably only care about the definition of members of MyNamespace::MyClass. This is heavy-handed and it communicates the intent poorly.
A possible alternative to #1 is a using-declaration which includes only the identifier you're interested in:
#include "MyClass.h"
using MyNamespace::MyClass;
int MyClass::foo() { ... }
I'd like also to add that if you decide due to some reason to implement a template specialization in a cpp file and just rely on using namespace you will run into the following problem:
// .h file
namespace someNameSpace
{
template<typename T>
class Demo
{
void foo();
};
}
// .cpp file
using namespace someNameSpace;
template<typename T>
void Demo<T>::foo(){}
// this will produce
// error: specialization of 'template<class T> void someNameSpace::Demo<T>::foo()' in different namespace [-fpermissive]
template<>
void Demo<int>::foo(){}
Otherwise if you apply #2 method this will be fine.
I'd like to add one more way, using a using-declaration:
#include "MyClass.h"
using MyNamespace::MyClass;
int MyClass::foo() { ... }
This saves you from typing the namespace name many times, if a class has many functions.
I think the practice #1 is not correct C++ code at all. This code snippet defines ::MyClass::foo symbol, where the real full qualified name is ::MyNamespace::MyClass::foo.
To learn about namespaces you can read section 7.3 of the draft let's say for standard http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3690.pdf
This concept is pretty old from 1998 or so, so you can use any standard or books of B.Stroustroup to learn about it.
In C++ language the namespace is a named scope. The namespace, as opposed to the class definition, is open to adding new functions to it.
The construction "using namespace NS;" in C++ is called as using-directive, and it can be used for several goals in my practice:
You can use this directive in another namespace to combine(mix) names from a different namespace.
In the context of the compilation unit it appends synonyms to all variables in namespace NS.
To define symbol, you can use two mechanisms -
you can use the explicit qualification with all namespaces via operating in global namespace in C++ source file.
Or You can open namespace and add definitions to it (practice #2).