I'm a bit confused by global constants. My (beginner level) understanding is that 'global' variables are defined outside of a block and have program scope (source: http://www.learncpp.com/cpp-tutorial/42-global-variables/). But the program:
#include <iostream>
const double x=1.5;
int main(){
std::cout << "1) x=" << x << std::endl;
double x=2.5;
std::cout << "2) x=" << x << std::endl;
//const double x=3.5;
return 0;
}
compiles in g++ (GCC, latest 64-bit version) without any problems, even with -Wall.
The output:
1) x=1.5
2) x=2.5
This is confusing to me. The fact that the first cout evaluates means that main recognises 'x' as a 'global' variable (it wasn't defined in main's scope). If that is the case, why does it let me redefine 'x'?
Then, if you uncomment the commented third declaration, g++ throws up a redeclaration error. Meaning, my first declaration can't have been 'global', in the sense I defined :S
edit: okay, question has nothing to do with global variables, but scopes: e.g same problem in http://pastebin.com/raw.php?i=V5xni19M
#include <iostream>
const double x=1.5;
At this point in code, there is one object named x in the global scope, and it is of type const double.
int main(){
std::cout << "1) x=" << x << std::endl;
At this point, there's still just one x visible (the global one), so that's what the name x refers to.
double x=2.5;
At this point in code, you've introduced an object named x into the scope of main(). That scope is nested inside global scope, so now you have two objects named x:
x in global scope of type const double
x in the scope of main() of type double
The local x hides the global x. If you want to access the global x inside main(), you can refer to it as ::x.
std::cout << "2) x=" << x << std::endl;
double x=3.5; //uncommented
No you're trying to introduce another object named x into the scope of main(). This is not possible, there already is one x in that scope, so it fails.
The second x is not a redefinition. It is hiding the global x.
This is something to watch our for particularly when dealing with inheritance:
struct Base
{
void AwesomeFunction() { }
};
struct Derived : public Base
{
// This definition 'hides' Base::AwesomeFunction
void AwesomeFunction() { }
};
This hiding is only allowed because the second x is in a smaller scope than the global x.
You get a redfinition error for the third x because the third and the second x are at the same scope 'level'.
Use ::x to access the global variable from your program. Right now you are making a local variable and a global. When you first print x it can't find a local one so it assumes you meant the global. After you make your local x it no longer defaults to the global.
What happens in your code is that the local variable takes precedence over the global variable if they take up the same name. You can use your global variable in any block throughout the program, while the local one will be disposed of at the end of its block (main). The compiler won't however let you declare two local variables of the same name in one block.
Declarations at an inner scope (like main) are allowed to shadow declarations at an outer scope (like file scope). Your third declaration of x is at the same scope as your second, so that is a redeclaration error.
You're not redefining the global variable; you're defining a separate local variable with the same name.
C++ allows you to reuse a name to declare something else in a narrower scope like this; technically, the declaration in the inner scope hides the one in the outer scope so that, between the declaration and the end of the function, x refers to the local variable. You can still access the global variable by qualifying it with its namespace: ::x.
The third declaration would try to reuse the name in the same scope, which is not allowed.
Related
From C++ ISO draft 2020, 6.2, first paragraph:
A declaration (Clause 9) may introduce one or more names into a
translation unit or redeclare names introduced by previous
declarations. If so, the declaration specifies the interpretation and
semantic properties of these names.
Does redeclaration only happens when all semantic properties are the same, or just the same name is needed?
int main() {
int a = 12;
{
char a;
}
}
In the code above, what happens in the inner rounded brackets? a declaration or a redeclaration?
In the following code, is there a declaration or redeclaration?:
int main() {
int a = 12;
{
int a ;
}
}
In both cases the inner declaration of variable a hides the outer variable a. So if you use variable a in any manner, inside the inner block then it will refer to inner a.
For example, if you modify the first case as follows:
int a = 12;
{
char a;
decltype(a) p;//p is a char type instead of int
}
then the type of variable p is char and not int. This is because as i said when you write decltype(a) then this a inside the parenthesis refers to the inner variable a instead of the outer variable a i.e., the inner declaration of a hides the outer a. And since the inner a is of type char so p will be of type char.
Now lets modify your example 2 as follows:
int a = 12;
{
int a = 15;
std::cout<<a <<std::endl;//this will print 15
}
In this case also the inner declaration(which is also a definition) of a hides the outer a. So when we write std::cout<<a; , we are referring to the inner a which has value 15. And so we will see 15 printed on the screen. Again the inner declaration of a hides the outer a.
Declaration of a variable or function simply declares that they exist somewhere in the program and specify the exact type. This is different from definition which actuallys allocate storage space for the variable or function.
What appear to be "Redeclarations" are valid in some cases in c++.
Here is one example of a valid redeclaration:
// file1.c
int Count;
// file2.c
void foo(void) {
extern int Count;
Count++;
}
Both of your examples are NOT re-declarations. They are simply declarations of a new local variable that has the same name as another local variable in the outer scope. The inner local variable shadows (hides) the outer one.
If you had not introduced a new scope with {} then a would have been redefined.
Both variables are alive at the same time, the lifetime of the inner one is included in the lifetime of the outer one. At the end of the inner scope, the inner variable's lifetime will be over, and the outer variable can be easily accessed again.
You can see this clearly demonstrated with the following little example:
struct A {
A() { cout << "Object being created\n"; }
~A() { cout << "Object being destroyed\n"; }
};
void main() {
A a1;
cout << "Beginning inner scope\n";
{
A a1;
}
cout << "End of inner scope\n";
}
In C++ ( and C and Java and others ) it is legal for the same name to be used within multiple scopes - some compilers (e.g. gcc -Wshadow) can generate a warning about this since it can cause confusion.
for showing you, I made a very minimalist example of my problem about 1 header and 2 .cpp files. All I do is calling myfunc() and this shall get a value by cin>>. And then main shall print the value (+3). I get the error "a is not defined" for the main.cpp.
I thought static is somehow helping here, but it's not. I don't understand what the problem is.
(I am aware, that I could write cout << myfunc()+3; but it's for a general purpose).
header.h:
#ifndef header_h
#define header_h
int myfunc();
#endif
main.cpp:
#include <iostream>
#include "header.h"
int main()
{
myfunc();
std::cout << a + 3 << std::endl;
}
second.cpp:
#include"header.h"
int myfunc()
{
static int a;
std::cin >> a;
return a;
}
Your a variable is declared inside the function (so it is local to the scope) and hence cannot be accessed outside of it.
If you want access from main, declare it outside the scope of the function (a global variable).
int f() {
int x = 23 ;
return x ;
}
int main() {
std::cout << f() << std::endl ;
std::cout << x ; // Error! x is local to f() and there is no x declared globally or inside main()'s scope.
}
You could do something like this :
int a = myfunc();
std::cout << a ; // Now possible!
Edit: static variable declaration has nothing to do with scoping rules or accessibility. Declaring static merely implies a change in the life-time policy of the variable i.e. its life-time is throughout the program execution duration instead of the duration in which the instructions in the scope (in which the variable is declared) are executed. Thus declaring static does not imply that a variable can be accessed outside of its scope.
"static" does two things: It creates a variable that exists once through the life time of the program, and it makes sure that the variable is accessible by name only in the one compilation unit where it is defined (so if another compilation unit by chance declares something static with the same name, there is no clash).
That means that by design you cannot access a static variable declared in second.cpp from main.cpp. That's absolutely intentional.
In addition, your variable a is declared inside a function. That means it can be only accessed inside that function. So not even code in other functions in second.cpp can access it by name. Again, fully intentional.
Apart from that, if you got around these problems (and you can), storing the result of a function in a global variable and accessing it through that variable is usually considered a very bad programming practice.
Consider the following code fragment:
int test; //global variable
class Base
{
int test; //private member of Base
public:
void getit()
{
cin>>test;
}
};
class Derived: public Base
{
public:
void check()
{
test++; //neither access global test nor the member of Base
}
};
In the above code, observe the variable test. It is first declared globally and then again declared inside the class in private scope.
My question first question is how the compiler is allowing multiple declaration for the variable test and why not giving an error?
Also, when the function check() tries to access test, compiler gives an error. I know the private members are not inherited and are not accessible outside class, but their exists a global variable, which must be accessible.
Second question is which test is present inside check() whether the global one or one which it is declared inside class Base? Also, how to access that global test?
How the compiler is allowing multiple declaration for the variable test and why not giving an error?
This is a basic tenet of C++'s scope rules. Conceptually, it's no different than declaring a local variable with the same name as a global variable.
The test in the global namespace does not conflict with the test member variable (though one does "hide" the other when used in an unqualified way, because the member will take priority during lookup).
This is simply how the language is designed, and it's a good thing.
Also, when the function check() tries to access test, compiler gives an error.
The important thing to consider is precisely what that error is. It's not telling you that no symbol test can be found; it's telling you that it's found the member variable, and that you have no access to it.
That tells you that access specifiers do not affect visibility, only accessibility:
your member test still hides the global test, even though you can't access it.
To specify the global test, you'd need to write ::test.
The global variable is hidden by the local test variable. Hence you do not get a compiler error. You can see more details here.
To access the global variable within the class, you have to use,
::test
Consider the following example
#include <iostream>
int x = 1;
int main()
{
std::cout << "x = " << x << std::endl;
int x = 2;
std::cout << "x = " << x << std::endl;
std::cout << "x = " << ::x << std::endl;
{
int x = 3;
std::cout << "x = " << x << std::endl;
std::cout << "x = " << ::x << std::endl;
}
std::cout << "x = " << x << std::endl;
std::cout << "x = " << ::x << std::endl;
}
Any name declared in internal declarative region hides the same name declared in the enclosing declarative region.
As for your example then member functions start to seek names in the scope of the class where they are declared.
So member function getit
void getit()
{
cin>>test;
}
starts to seek name test in the scope of the class and indeed such name is declared in the class.
As for function check then access method does not influense on the search of the name. The finction finds the name in the scope of its base class. As this name is not accessible the compiler issues an error.
I saw usages of these two phrases: global scope and global namespace. What is the difference between them?
In C++, every name has its scope outside which it doesn't exist. A scope can be defined by many ways : it can be defined by namespace, functions, classes and just { }.
So a namespace, global or otherwise, defines a scope. The global namespace refers to using ::, and the symbols defined in this namespace are said to have global scope. A symbol, by default, exists in a global namespace, unless it is defined inside a block starts with keyword namespace, or it is a member of a class, or a local variable of a function:
int a; //this a is defined in global namespace
//which means, its scope is global. It exists everywhere.
namespace N
{
int a; //it is defined in a non-global namespace called `N`
//outside N it doesn't exist.
}
void f()
{
int a; //its scope is the function itself.
//outside the function, a doesn't exist.
{
int a; //the curly braces defines this a's scope!
}
}
class A
{
int a; //its scope is the class itself.
//outside A, it doesn't exist.
};
Also note that a name can be hidden by inner scope defined by either namespace, function, or class. So the name a inside namespace N hides the name a in the global namspace. In the same way, the name in the function and class hides the name in the global namespace. If you face such situation, then you can use ::a to refer to the name defined in the global namespace:
int a = 10;
namespace N
{
int a = 100;
void f()
{
int a = 1000;
std::cout << a << std::endl; //prints 1000
std::cout << N::a << std::endl; //prints 100
std::cout << ::a << std::endl; //prints 10
}
}
"Scope" is a more general term than "namespace". Every namespace, class and code block defines a scope in which names declared inside it can be used; a namespace is a container for names declared outside classes and functions.
"Global scope" and "global namespace" can be used more or less interchangeably; the scope of a name declared in a namespace covers the whole of that namespace. Use "namespace" if you're specifically referring to the namespace, and "scope" if you're referring to the visibility of names inside it.
When you declare a global variable int i for example, we say i is in the global namespace and has the global namespace scope. That's all.
Excerpt From C++03:
3.3.5 Namespace scope
The outermost declarative region of a translation unit is also a namespace, called
the global namespace. A name declared in the global namespace has global namespace
scope (also called global scope).
Scope denotes the lifetime of an object, you can have a global variable that will exist as long as your program executes, or you can have a variable with a block scope that will exist as long as that block of code executes. Consider this example:
#include <iostream>
int a = 100;
main () {
int a = 200;
std::cout << "local a is: " << a << std::endl;
std::cout << "global a is: " << ::a << std::endl;
return 0;
}
When executed the statement will print local a is: 200, that is expected obviously, because we're redefining a in main which leaves in the scope of it's enclosing block. We also print the global ::a which again prints the expected value 100, because we have asked for the global namespace ::.
A namespace semantics are mostly logical, it is a way of isolating symblos from one another, in the hope to avoid name clashes, it does not affect the lifespan of an object.
Scope on the other hand, denotes the lifespan of an object, the global a sprung into existence before the local a because it gets constructed much earlier than main gets executed. However, scope also forces a namespace on the symbol, but not in the same way that a namespace does. There are different kind of scopes, global, class, function, block, file etc...
The confusing part is that scope is sometimes overloaded to denote the visibility of a particular symbol, which is something borrowed from C, where the notion of namespaces did not exist and scope was used to denote both, lifespan and visibility. In C++, however the rules changed a bit,but the term scope is still used the same way because the two languages share a great deal of concepts.
#Dmitriy Ryajov
The topic is a little bit old but I want to offer my help about this. I think that you should not make things more complicated than they really are. Scope of an identifier is the part of a computer program where the identifier, a name that refers to some entity in the program, can be used to find the referred entity. So the term scope only applies to identifiers and we should not mix it with the lifetime of the object. They are somewhat connected but should not be mixed up. The lifetime of the object is denoted by where we allocate the memory for that object. So, for example, if a memory is allocated on the stack, it will be freed as soon as the function finishes. So it depends on where we store the object and that denotes its lifetime. The scope only says: "Here is a name for an object and we can use this name for the object till then and then". So, as I said, the term scope is only for identifiers of the objects and the lifetime is something else wich is denoted by where we store the object.
Additionally, I want to say something about linkage which is closely related to this. This can be also sometimes confusing. Let's say we have some identifiers in the translation unit that refer to some objects. Whether the same identifiers in other translation unit will refer to the same entities is denoted by the linkage. So, for example, if an identifier has an external linkage, we can refer to the entity that this identifier refers to but from other translation unit by declaring it with keyword extern. Now, let's say we don't want to use that entity in other translation units. Then, the entity will exist till the program finishes but when we don't declare it, we won't be able to refer to it. Also note that now i mixed the terms linkage and lifetime. But this is because only global entities have external linkage. An identifier inside a function can't be refered to from the other parts of the program.
Conclusion: Always try to keep things simple. I was surprised how different people talk about these terms differently. The whole process of separate compilation is confusing, because there are multiple terms which have almost the same meaning and probably everyone will get stuck at this point.
If you go to the accepted answer of this post
Could someone please elaborate on why he uses:
double temp = ::atof(num.c_str());
and not simply
double temp = atof(num.c_str());
Also, is it considered a good practice to use that syntax when you use "pure" global functions?
It says use the global version, not one declared in local scope. So if someone's declared an atof in your class, this'll be sure to use the global one.
Have a look at Wikipedia on this subject:
#include <iostream>
using namespace std;
int n = 12; // A global variable
int main() {
int n = 13; // A local variable
cout << ::n << endl; // Print the global variable: 12
cout << n << endl; // Print the local variable: 13
}
:: is the scope resolution operator. Its use in this scenario, as a unary operator, is to ensure that the name (atof) is always looked up in the global scope -- this can be useful to prevent name hiding from interfering with the lookup.
The :: operator is scope resolution operator.
when used with class specifier as like A::a, it is to access the data memeber a of the class A.
when used without any specifier, it access the global variable.
It is used mainly in the following contests.
To refer to the global variables.
To refer to the static members of the class
To avoid ambiguites, when a class inherits from multiple [ non-virtual
base ] classes.
With using directive, to use the base class functions in the derived class, when there is a function in base class with name same as that of the derived class, but for a different type.
To access the functions defined in the global scope, when you have a function defined with the same signature, as in double temp = ::atof(num.c_str());
To create objects of the nested classes.
Lets say you have two versions of a function f() one defined outside a namespace and one defined inside. Now lets say you have one more function g() in the same namespace. Now if you do f() inside g() it will call the one defined in the same namespace. But if you want to call the global version you need to do ::f()
::func() means that this function is not affiliated with any specific class. It is used when there exist many functions with the same name, and to avoid confusion between the one you want and specific member functions you precede the function name with the scope operator.
From C++ Primer, 4th edition, section 17.2.1:
"Names defined at global scope - names declared outside any class, function, or namespace - are defined inside the global namespace. The global namespace is implicitly declared and exists in every program. Each file that defines entities at global scope adds those names to the global namespace.
The scope operator can be used to refer to members of the global namespace. Because the global namespace is implicit, it does not have a name; the notation
::member_name
refers to a member of the global namespace."