A coworker routinely writes something like this:
::someObject->someMethod(anAttribute, anotherAttribute);
someObject is a global variable.
Those two colons seem strange to me. The code compiles and runs just fine without them.
The coworker claims that those colons make someObject explicitly global and thus prevent confusion with a possible local someObject. I would think that you would not be able to define someObject locally if it was already defined globally?
Could you shed some light on what those colons mean and whether they are necessary?
Your coworker is right. You can indeed define a local someObject which would hide the global someObject within that scope:
SomeClass* someObject = ...;
// here the global object is visible
someObject->someMethod(anAttribute, anotherAttribute); // calls the global object
void someMethod() {
SomeClass* someObject = ...;
// here the local object hides the global
::someObject->someMethod(anAttribute, anotherAttribute); // calls the global object
someObject->someMethod(anAttribute, anotherAttribute); // calls the local object
}
// here again only the global object is visible
someObject->someMethod(anAttribute, anotherAttribute); // calls the global object
Scopes can be embedded within other scopes recursively, thus you may have a namespace within global scope, a class within a namespace, an inner class within the class, a method within an inner class, a block within the method... etc. And you may have variables/classes/methods/... of identical names in any of these scopes. So identifying what entity a specific name is referring to is not a trivial task in C++. It is known as name lookup.
In brief, whenever the compiler finds a name, it looks up that name starting from the innermost scope. I.e. inside someMethod, the name someObject is matched by the object defined locally. ::someObject overrides this default behaviour and makes the compiler search only within the outermost (global) scope, thus it finds the global object instead ofthe local.
You can indeed define a someObject locally even though there is a global one. The two variables have different scope, so the compiler knows there's a difference between the two, and the double colons let you refer to the global one.
This also applies to classes outside of a namespace; i.e., to refer to a class Foo from the class Bar::Foo, you use ::Foo to tell the compiler you are talking about the one that isn't in a namespace.
Here's an example that shows it working:
#include<stdio.h>
int someInt = 4;
int main() {
int someInt = 5;
printf("%d", someInt+::someInt);
return 0;
}
If you compile and run that piece of code, it will output 9.
The coworker claims that those colons
make someObject explicitly global and
thus prevent confusion with a possible
local someObject.
Yes - it means the function can be, and must only be, matched in the global namespace. It makes it obvious you're dealing with a global, and would prevent accidental matching against something more local (beit function local, an object member, namespace member, in a namespace you're using, a Koenig lookup match etc.).
I would think that you would not be
able to define someObject locally if
it was already defined globally?
It would be a very bad idea to make it an error. Say a team of programmers decides they want to add a variable called "last_error" to their namespace: they shouldn't have to worry if existing functions in the namespace use the same name for a local variable. If you copy a function from one namespace or class to another, you shouldn't have to make error-prone identifier substitutions in the implementation.
Regarding the benefits of ::, consider:
namespace X
{
void fn() {
rip(data, bytes); // MP3 rip this data
}
}
...then fn() needs to be moved quickly into namespace Y...
namespace Y
{
void rip(const char* message, int exit_code); /* for fatal errors */
...
}
...a casual copy-paste into the guts of Y could easily overlook that log won't match the same global function it used to when fn was in namespace X, but - as illustrated - the functionality may differ markedly :-).
You can think of each namespace, class/struct and functions forming a tree, where each level must be uniquely keyed (i.e. no same-named classes in the same namespace), but decendents are always independent of each other and their ancestors. Increasing freedom to vary independently is essential for letting many people work simultaneously on a big problem.
Could you shed some light on what
those colons mean and whether they are
necessary?
In this specific usage, the :: probably isn't strictly necessary. It adds a little protection, but makes it harder to move the variable to a more local scope later - though that's not so important because the compiler will tell you about the places that continue to refer to ::x after x is moved.
Just a minor add on to all other nice points which have come in the response.
Basically :: invokes qualified name lookup in the global namespace. However it is not guaranteed to be problem free especially in the face of indiscriminate using directives.
The code shown illustrates an important property of qualified name lookup. The point here is that namespaces nominated by using directives in the global namspace are searched. However using directives in namespaces that have the name being searched are skipped.
namespace Z{
void f(){cout << 1;}
}
namespace Y{
void f(){cout << 2;}
using namespace Y; // This namespace is not searched since 'f' is found in 'Y'
}
#if 0
namespace Z{
void f(){cout << 3;}
using namespace Y; // This namespace is not searched since 'f' is found in 'Y'
}
using namespace Z;
#endif
using namespace Y;
int main(){
::f(); // Prints 2. There is no ambiguity
}
In the code shown, if lines with the #if directive are enabled, there is an ambiguity in resolving the name 'f'.
Related
#include <iostream>
using namespace std;
#include "other_library.h"
struct Foo
{
Foo() { cout << "class\n"; }
};
int main()
{
Foo(); // or Foo() in any expression
}
This outputs class, or so we would think. The problem is that if other_library.h happens to have a function called Foo whose return type is suitable to appear in whatever expression we used Foo in then it silently changes the behaviour, e.g.:
int Foo() { cout << "func\n"; return 1; }
causes func to be output without any code changing in main. This is bad because of the possibility for insidious and hard-to-detect bugs ; even if it is not malicious intent on the part of other_library, a name clash could go undetected.
What is a good way to deal with this problem? It was originally raised by Dan Saks in 1997, and one suggested resolution is that all classes should be typedef'd:
typedef struct Foo Foo;
as the compiler does have to report a clash between a typedef-name and a function name. However this does not appear to be common practice - why not?
Clarification: this question is about good practices for our code to stop this undetected behaviour change happening without us noticing. (As opposed to how to solve it once we have realized that it is happening, which is easier -- e.g. rename our class).
typedef struct Foo Foo;
as the compiler does have to report a clash between a typedef-name and
a function name. However this does not appear to be common practice -
why not?
I hold this truth to be self-evident: cumbersome code is cumbersome. You can actually rather easily fix this by working in a namespace of your own (which, assuming the header file is C++, too, the other_library should also do.
Unfortunately, you cannot avoid this. From C++11 standard (3.3.10):
A class name (9.1) or enumeration name (7.2) can be hidden by the name of a variable, data member, function, or enumerator declared in the same scope. If a class or enumeration name and a variable, data member, function, or enumerator are declared in the same scope (in any order) with the same name, the class or enumeration name is hidden wherever the variable, data member, function, or enumerator name is visible.
The only way to guard against it is the typedef trick you pointed out (thanks for that!), using namespaces, or adhering to naming conventions (the latter not helping when dealing with 3rd party code). You could also try to wrap the include in a namespace (shown bellow), but as the comments pointed out, this could cause link errors in certain situations.
namespace otherlib {
#include "other_library.h"
}
Then:
otherlib::Foo();
current best practises protect against this already
Naming Conventions, such as
void camelCase() vs class PascalCase
namespaces
wrapper libs for everything not modern C++
I though I had a good understanding of how C++ worked but I'm confused about a piece of its use. If I declare a class instance globally in a .cpp file (not associated with a class) like
Class b(constructor parameters)
it doesn't cause a problem. My understanding was that declaring classes this way allocated them in the stack frame for the method they were in instead of on the heap. But if I declare this globally there is no method and thus no stack frame right? Why am I allowed to do this and more importantly what is happening and is this any kind of big no no in C++?
It is just a static object. It is treated like any other global variable.
It will not be tied to any stack frames and will be created when the anything in the file is loaded for the first time.
Generally, people will not recommend relying on globals from a design perspective. It depends though, they can be reasonable.
If you are doing any sort of threading they can be an issue. You also want to minimize different parts of your application knowing that things are global variables, it leads to a lot of spaghetti code.
If the variable is not referenced outside of the file, or for cross-cutting concerns, then sometimes it can be a good thing.
The best advice is to avoid it when you can, don't over design it when you can't.
Objects that are global variables (or more precisely variables "at namespace scope") have static storage duration. This means they live until the end of the program, and they are initialized during program startup (either during the static or the dynamic initialization phase).
The order of initialization is not generally specified except that all such global objects are initialized before main() is called, and that the initialization does not introduce data races.
(Common techniques to sequence mutually dependent global initialization is to replace naked global variables with a global getter function and a block-static variable:
Foo & getFoo() { static Foo impl; return impl; }
Now any other global using getFoo() in its own constructor will be initialized after impl.)
Quick Comment
You may want to change your post's title to:
Declaring a Global Class Instance in a C++ file ?
or:
How does a global object, its declared, and, later, stored in memory, in C++ ?
I may be wrong, but, seems to me, like you have work with other Object Oriented, programming languages, reference based, and try to apply your experience on C++.
Example
C++, its a mix of: Procedural Programming & Object Oriented Programming, and some other stuff, like functional.
You may want to see a Procedural Program, as a single object, which class has been already declared & make an instance. and, has this public main method, automatically executed, like a constructor.
When you read a C++ file like this:
// file: "example.cpp"
// class declaration without local variables
class CoordinateClass
{
int x;
int y;
};
// a global variable
CoordinateClass MyCoordinates;
int main (char[][] args)
{
// dont care about this in this example
int ErrorCode = 0;
// DoSomething();
// dont care about this in this example
return ErrorCode;
} // int main()
You may want to think as this:
// file: "example.cpp"
public: class example: program
{
public:
// class declaration without local variables
class CoordinateClass
{
int x;
int y;
};
// a global variable, works like a field of a class
CoordinateClass MyCoordinates;
int main (char[][] args)
{
// dont care about this in this example
int ErrorCode = 0;
// DoSomething();
// dont care about this in this example
return ErrorCode;
} // int main()
};
// this is done automatically:
example MyExample;
MyExample.main();
Cheers.
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.
My question: What exactly is the out of class definition of k doing under the hood to make sure it's address is available?
#include <iostream>
using namespace std;
class A {
public:
static const float k = 7.7;
};
//const float A::k; --> without this line compiler error
int main()
{
cout << &A::k;
}
The class "definition" is actually only providing a "declaration" of A::k. Yeah, I know it's confusing, but the idea is to allow the class definition to be in a .h (included from multiple .cpp sources) without creating ambiguities: one, and only one, of those .cpp sources, must provide the actual definition to match A::k's declaration (the latter being part of class A's definition).
Other answers have already given the how to fix it -- I'll go more into the why.
When you do this:
#include <iostream>
using namespace std;
class A {
public:
static const float k = 7.7;
};
int main()
{
cout << A::k;
}
The compiler is probably in reality generating this:
#include <iostream>
using namespace std;
class A {
public:
static const float k = 7.7;
};
int main()
{
cout << 7.7;
}
which means there will be no link-time dependency between this translation unit and A::f -- the compiled code doesn't reference A::f at all!
However, when you use &A::f, you force the compiler to generate an address for A::f. Therefore that translation unit does have a dependence on A::f. Since you have not defined it, you get a linker error, because the linker cannot find an address for it. For the address to exist, A::f must be defined in one and only one translation unit. To choose the translation unit in which it should reside, you need to define it there.
You also have an invalid code issue with your class above though -- only static const integral members may be initialized with the syntax you've used (putting k = 7.7 in the class body) -- float is not an integral type.
It sounds like you're wondering why the variable needs to be defined even though you aren't accessing it.
To print its address, it needs to have an address. To have an address, it must exist. To exist, it needs to have a definition and the linker needs to assign it a place in global variable space. So, there really isn't a middle ground.
"Under the hood," the definition tells the linker what the initializer for the global is. (In this case, the initializer is in the class block. But that's nonstandard. The official way is to write const float A::k = 7.7;) Without knowing that, it can't produce the executable file.
Also, unless the compiler performs impossibly detailed analysis, it can't really tell that operator << doesn't somehow pass that pointer to some other function or OS service that will access the value of k.
If you could define like static const float k = 7.7; as you wish, you will end up in multiple definitions (since static members will be defined only once), wherever you are including it.
To avoid that the definition is made reside separately in a cpp file.
From C++ standard docs sec 9.4.1,
A static data member is not part of the subobjects of a class. There is only one copy of a static data member shared
by all the objects of the class.
Also 9.4.2 states that,
The declaration of a static data member in its class definition is not a definition and may be of an incomplete type
other than cv-qualified void. The definition for a static data member shall appear in a namespace scope enclosing the
member’s class definition.
Hope it helps..
The one which is inside the class is the declaration of the variable k. You need to define it in exactly one translation unit in order to link your program correctly. Hence that statement is required.
A static variable can be deemed as data shared by all the objects of the class and hence only one copy of this variable should be created. With this said, with whom should lie the responsibility of allocationg memory for this member? Obviously it can't be object's responsibility as there could be multiple objects which would raise another challenge as to which object should allocate memory for this member.
So typically compliler expects out of class, explicit definition of this member and hence the line:
const float A::k;
This ensures that the static member variable is accessible to all the objects of the class. The memory for this variable is allocated on globally accessible memory.
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."