scope of non-member, non static variables and methods - c++

Test.h
class Test
{
public:
Test();
//some methods
private:
int var;
//some vars
}
Test.cpp
#include "Test.h"
int a;
void func()
{
//some code here
}
Test::Test()
{
//some code
}
Variable a and function func() are non-member and non-static.
What is the lifetime of variable a and function func()?
Consider Test class as a part of a shared library. Can other classes of that library access a or func() by resolution operator ?
What is difference between static declaration of variable a/ func() and nonstatic declaration of a/func() ?

Variables and functions have the same scope: they exist from their point of declaration onward.
This is relatively different from attributes and methods of a class whose scope is limited to the class itself and where order matters less (though it may... for types).

The MSDN page is the answer to your question. It defines scope and Lifetime.
a have scope and life time through out the file since its global.
func() doesnt have scope or lifetime. they only have visibility.
if its part of shared library also functions and global variables can be accessed by other parts provided library is visible.
In this case being static doesnt make much of a difference. But local variables when made static gets global scope but will have only local visibility.

Variable a is a global variable, its scope is entire program runtime i.e its created during your program startup and destroyed during program exit. func is a global function and functions do not have any concept of scope attached to them.

In C++ a scope, defined by C++11 ยง3.3.1/1, is a (possibly discontiguous) region of text where a name can be used unqualified to refer to the same entity.
A potential scope is the scope a name will have when there are no declarations of the same name within the potential scope.
The scope of your variable name and function name extends from the declaration, to the end of the file.

Variable "a" is a global variable to Test.cpp
and "func" is a normal function in Test.cpp.
Edit section:-
But u can use the same variable & method in different place if u do the same as listed below.
//file1.h
#ifndef FILE1_H
#define FILE1_H
extern int a;
extern void func();
#endif
//end of file1.h
//file1.cpp
#include"file1.h"
int a; // a=0 as it is global variable
static int x = 10;// Scope is limited, it can only be used in file1.cpp
static void func2(){
int z = x;
z = x+z;
//... some thing u r doing
}
void func(){
//... some thing u r doing
}
//end of file1.cpp
//file2.cpp
#include"file1.h"
//U can use variable "a" & method "func" defined in file1.cpp . For an eg:-
int add(int b){
func();//func defined in file1.cpp but used here
//func2(); //It will throw error if you remove the comment before func2 method as
//the scope of func2 is limited to file1.cpp as it is static method
return a+b;// a defined in file1.cpp but used here
}
int main(){
//some code exists here
return 0;
}
//end of file2.cpp
//================
There are lot of things by which u can play around. It just one of the example.
Like if you declare static global variable then scope of that variable is limited to that file only.
Variable "a" & "func" is accessible by other classes present in the same file where the Test Class is present.
If you declare any variable or method as static global variable then the scope of that variable & method is limited to that file as explained in above example.

Related

Forward declared variable not accessible in cpp file

Considering the example below:
header.h
extern int somevariable;
void somefunction();
source.cpp
#include "header.h"
somevariable = 0; // this declaration has no storage class or type specifier
void somefunction(){
somevariable = 0; // works fine
}
I couldn't find the answer to the following questions:
Why can't I just forward declare int somevariable and initialize it in the .cpp file?
Why is the somefunction() function able to "see" somevariable when declared using extern int somevariable, and why is it not accessible outside of a function?
extern int somevariable;
means definition of somevariable is located somewhere else. It is not forward declaration. Forward declaration is used in context of classes and structs.
somevariable = 0;
is invalid since this is assignment and you can't run arbitrary code in global scope.
It should be:
int somevariable = 0;
and this means define (instantiate) global variable somevariable in this translation unit and initialize it to 0.
Without this statement linking of your program will fail with error something like: undefined reference to 'somevariable' referenced by ... .
Use of global variable in any langue is considered as bad practice, sine as project grows global variable makes code impossible to maintain and bug-prone.

constexpr static member vs variable

I stumbled upon some C++11 code that looks like this:
// some_file.h
namespace blah {
class X {
public:
constexpr const static std::initializer_list<uint64> SOME_LIST =
{1,2,3};
};
}
// some_file.cpp
#include "some_file.h"
namespace blah {
constexpr const std::initializer_list<uint64> X::SOME_LIST;
}
Which compiles fine. I assume the definition in the cpp file is used to avoid symbol duplication in each file that includes the header (please correct me if I'm wrong).
I then tried the following:
// my_file.h
namespace bleh {
constexpr const static char SOME_CONSTANT[] = "yay";
}
// my_file.cpp
#include "my_file.h"
namespace bleh {
// if I add this or any other variation, compilation breaks!
//constexpr const static char SOME_CONSTANT[];
}
The code above does not work if I add an explicit definition in the .cpp file. So I am wondering: is there symbol duplication in the second case? If so, is there a way to define the variable without an enclosing class?
The static keywords mean two different things here:
When you declare a variable or function at file scope (global and/or namespace scope), the static keyword specifies that the variable or function has internal linkage. When you declare a variable, the variable has static duration and the compiler initializes it to 0 unless you specify another value.
When you declare a data member in a class declaration, the static keyword specifies that one copy of the member is shared by all instances of the class. A static data member must be defined at file scope. An integral data member that you declare as const static can have an initializer.
C++ needs you to define static class members somewhere, because the class symbol is global (and so is your member). This can't be done in the header because of multiple definitions.
In the second case every compilation unit uses its own variable and there is no global symbol.

Call static method in global scope

I have a class that store a collection of types. This types are registered by other class using a static method from the first class.
Here is some code :
in file classA.h
class A {
static void RegisterType(std::string name, bool (*checkType)(Json::Value toCheck));
}
In file classB.h
class B {
static bool CheckType(Json::Value toCheck);
}
In file classB.cpp
// In global scope
A::RegisterType("B", &B::CheckType);
When I do this in classB.cpp my compiler (Visual Studio 2010) think I want to redeclare the A::RegisterType() function.
I try to change return type of A::RegisterType() from void to bool. And then assign the returned value to a variable in classB.cpp :
// In global scope
bool tmp = A::RegisterType("B", &B::CheckType);
This way it does work, but I add a variable in global scope and I don't want to.
How can I call A::RegisterType() from global scope without assign his result to a variable ?
Another question is how can I register the "B" type from classB.cpp ?
There are no "freestanding" function calls in C++ : you can call RegisterType() from another static method (e.g., from main())
A workaround is to mimic a static constructor :
struct StaticInit
{
StaticInit()
{
A::RegisterType("B", &B::CheckType);
}
};
class B
{
// ...
static StaticInit si; // Will force the static initialization
};
You can't call functions in the global scope of a file. It must have a scope that relates to the one of the main() function of your program (as in, if you go up in the call stack, you end up in your main() function), or to the scope of a constructor of a class/struct of which you create a static object.
A cpp file isn't executed. It just contains code that will be compiled.
In your case, you could create a static variable of a custom class in your cpp file whose default constructor calls this function.
From language-lawyer point of view, 3.5 Program and linkage states:
A program consists of one or more translation units (Clause 2) linked together. A translation unit consists of a sequence of declarations.
So you can't have statements in global scope, you have to place your call inside main() or inside a constructor of some static variable as suggested by quantdev.
Generally, CPP sees A::RegisterType("B", &B::CheckType); in global scope as declaration and not invoke it as function call.
So either you have to assign it to a global variable as you mentioned in bool tmp = A::RegisterType("B", &B::CheckType); or you have to do as suggested by quantdev

An extern variable located in a function?

According to wikipedia:
http://en.wikipedia.org/wiki/External_variable
An external variable may also be declared inside a function.
What is the purpose of an extern variable being declared within a function? Would it have to be static too?
It allows for restricting access to a global to some scope:
int main()
{
extern int x;
x = 42; //OKAY
}
void foo()
{
x = 42; //ERROR
}
int x;
The external declaration goes inside a function. It simply means that no other functions can see the variable.
void func()
{
extern int foo;
foo ++;
}
void func2()
{
foo--; // ERROR: undeclared variable.
}
In another source file:
int foo; // Global variable. Used in the other source file,
// but only in `func`.
It is just a way to "isolate" a variable, so it doesn't accidentally get used in places where it isn't supposed to be used.
The only difference between declaring an external variable at namespace scope:
extern int x;
void foo() {
cout << x;
}
and declaring it at function scope:
void foo() {
extern int x;
cout << x;
}
is that in the latter case, x is only visible inside the function.
All you're doing is further tightening the scope of the extern declaration.
Here's an analogous example using namespaces:
At namespace scope:
#include <string>
using std::string;
void foo() {
string str1;
}
string str2; // OK
At function scope:
#include <string>
void foo() {
using std::string;
string str1;
}
string str2; // Error - `using` not performed at this scope
The extern keyword says that an identifier has external linkage. This means that it is linked to the same name anywhere else it is declared with external linkage. That is, the different instances of the name in different places refer to the same object.
Declaring an identifier inside a block (including the block that defines a function) gives it block scope. The scope of that instance of the identifier ends at the end of the block.
Combining extern with block scope allows a function to see an external identifier without cluttering the name space of other functions. (Nonetheless, it is often bad practice.)
The text refers to a non-defining declaration of an extern variable inside function. Extern definitions inside functions are illegal.
So, a non-defining declaration of an extern variable inside function simply means that you want to use that variable inside that function. The variable itself must be a global variable defined elsewhere.
Basically, if you don't need access to that global variable (defined elsewhere) in the entire translation unit and just need it inside that function, it is perfectly good idea to declare it locally. That way you are not polluting global namespace with identifiers no other function needs.

How to declare a global variable in C++

I know one should not use global variables but I have a need for them. I have read that any variable declared outside a function is a global variable. I have done so, but in another *.cpp file, that variable could not be found. So it was not really global. Isn't it so that one has to create a header file GlobalVariabels.h and include that file to any other *cpp file that uses it?
I have read that any variable declared outside a function is a global variable. I have done so, but in another *.cpp File that variable could not be found. So it was not realy global.
According to the concept of scope, your variable is global. However, what you've read/understood is overly-simplified.
Possibility 1
Perhaps you forgot to declare the variable in the other translation unit (TU). Here's an example:
a.cpp
int x = 5; // declaration and definition of my global variable
b.cpp
// I want to use `x` here, too.
// But I need b.cpp to know that it exists, first:
extern int x; // declaration (not definition)
void foo() {
cout << x; // OK
}
Typically you'd place extern int x; in a header file that gets included into b.cpp, and also into any other TU that ends up needing to use x.
Possibility 2
Additionally, it's possible that the variable has internal linkage, meaning that it's not exposed across translation units. This will be the case by default if the variable is marked const ([C++11: 3.5/3]):
a.cpp
const int x = 5; // file-`static` by default, because `const`
b.cpp
extern const int x; // says there's a `x` that we can use somewhere...
void foo() {
cout << x; // ... but actually there isn't. So, linker error.
}
You could fix this by applying extern to the definition, too:
a.cpp
extern const int x = 5;
This whole malarky is roughly equivalent to the mess you go through making functions visible/usable across TU boundaries, but with some differences in how you go about it.
You declare the variable as extern in a common header:
//globals.h
extern int x;
And define it in an implementation file.
//globals.cpp
int x = 1337;
You can then include the header everywhere you need access to it.
I suggest you also wrap the variable inside a namespace.
In addition to other answers here, if the value is an integral constant, a public enum in a class or struct will work. A variable - constant or otherwise - at the root of a namespace is another option, or a static public member of a class or struct is a third option.
MyClass::eSomeConst (enum)
MyNamespace::nSomeValue
MyStruct::nSomeValue (static)
Declare extern int x; in file.h.
And define int x; only in one cpp file.cpp.
Not sure if this is correct in any sense but this seems to work for me.
someHeader.h
inline int someVar;
I don't have linking/multiple definition issues and it "just works"... ;- )
It's quite handy for "quick" tests... Try to avoid global vars tho, because every says so... ;- )