Do member variables have external linkage? - c++

I have read this and it says that
names of classes, their member functions, static data members (const
or not), nested classes and enumerations, and functions first
introduced with friend declarations inside class bodies
have external linkage by default.. But what about the variables declared inside the class body that are not specified static? Also, it starts out with
Any of the following names declared at namespace scope have external
linkage
, but is class scope considered a namespace scope? I mean class scope and namespace scope are different, so why do they start out by saying that the following is applicable for the mentioned declared inside a namespace scope? I mean, for example, member functions are declared in class scope and they mention them as if it was namespace scope?

Following example:
class C
{
public:
int n;
};
C e;
namespace { C i; }
e has external linkage, i internal. How much sense would it make to speak of linkage of n now? If at all, you could consider n inheriting the linkage of the containing object, thus e.n would have external, i.n internal linkage – for better understanding only, I do not consider this as correct wording...

Quote from the standard:
A name is said to have linkage when it might denote the same object, reference, function, type, template, namespace or value as a name introduced by a declaration in another scope
Translation to plain English:
If you can redeclare it in another scope, it has linkage. Otherwise, nope.
You cannot redeclare a non-static class data member in another scope, so it has no linkage.

Related

Member's potential scope for struct vs namespace

Referring to this code:
namespace Y {
char f() { return y; } // error: y was not declared in this scope
char y;
}
struct X {
char f() { return x; } // OK
char x;
};
As per basic.scope.namespace#1:
The declarative region of a namespace-definition is its
namespace-body. Entities declared in a namespace-body are said to be
members of the namespace, and names introduced by these declarations
into the declarative region of the namespace are said to be member
names of the namespace. Its potential scope includes its namespace from the name's point of declaration onwards.
QUESTIONS
Is it correct to say that the error was due to the fact that Y::y is not yet declared in Y::f()?
I can't figure why there isn't a "reodering" for namespace members during declaration while for struct there is. What could be the reason for disallowing such behavior? Does the standard says something similar?
Is it correct to say that the error was due to the fact that Y::y is not yet declared in Y::f()?
Yes.
I can't figure why there isn't a "reodering" for namespace members during declaration while for struct there is. What could be the reason for disallowing such behavior? Does the standard says something similar?
The biggest hindrance for namespaces as opposed to classes, is that they are never "closed". You can always add members to a namespace by re-opening it in another translation unit and declaring more stuff in it. A class declaration however, for all its members, must appear entirely in a single translation unit. And there is no adding to it later.
[class.mem]/1
The member-specification in a class definition declares the full set
of members of the class; no member can be added elsewhere.
The problem for namespaces is intractable. But classes only require a little more, quite localized, work.
It is therefore much easier, both to a language designer and a compiler writer, to demand namespace declarations appear before they are used.
You should also note that you can only use other members of the class in only a specific set of places inside the definition.
[class.mem]/6
A class is considered a completely-defined object type ([basic.types])
(or complete type) at the closing } of the class-specifier. Within the
class member-specification, the class is regarded as complete within
function bodies, default arguments, noexcept-specifiers, and default
member initializers (including such things in nested classes).
Otherwise it is regarded as incomplete within its own class
member-specification.
You are mistaken thinking that for structures there is "reordering".
Consider the following structure definition.
#include <iostream>
struct A
{
char s[N];
enum { N = 10 };
};
int main()
{
return 0;
}
The compiler will issue an error because the name N is not yet declared when it is used in the array declaration. So neither "reordering" exists in the class scope. As for member functions then names used within a member function are at first searched in the class scope.
Moreover a name declared in a namespace can hide the same name declared in the outer namespace. As result the "reordering" breaks scopes of variables.

Why is it not allowed to put the `static` keyword for class member definitions in namespace scope?

struct A
{
static void f();
};
static void A::f() {} //illegal
Why's this not allowed? Am asking this because the rule seems inconsistent with other keywords.
You must put constexpr on both.
You can put inline on both, but you can also omit one of them. This is useful that you can omit inline in class definition, which is not important information of the interface.
But the rules for static on class members doesn't really make sense. Shouldn't it be consistent with constexpr?
I know static means internal linkage for namespace-scope functions, and this partly explains the current shape. But isn't distinguishing between free functions and class member functions having no ambiguity in namespace scope? For example, if you write static void A::f() {} it's unambiguous that you're defining a member function of A, if A is a class name.
The static in class have other meaning the static in a global or namespace.
when you declared symbol as static in the class, you don't want it to be a global static.
1. static member
In the class it is mean the symbol is class related not object related, means for member variable, there is only one instance for all the objects, and for function, it doesn't have access to non static members, which are object oriented. .
2. static global
In global scope, the static indicate the object or function is local only, and can't be exported (like using extern) to other files. in addition it let you use same name in other file for other variable. so if it located in header file, any file including the header, will have different instance of the symbol.
Therefore if you were allowed to use it in the global scope for a member, then there was an ambiguity.

Const variable in C++ function body

I believe I have it understod but I just want confirmation. If I have two functions,
function A()
{
const Vector3D vectorA(1.0f);
...
}
function B(float var)
{
const Vector3D vectorB(1.0f + var);
...
}
In the case of function A(), will vectorA only be constructed once in the program, no matter how many A() calls? I believe the compiler implicitly declares it static yes?
But in the case of B(), vectorB needs to be reconstructed each function call?
Both functions will create the variables every time they are called. There is no implicit static. Some compilers may choose to optimize but it is not part of the language specification.
The answer is no, however you are not that far off-track.
static is a very much overloaded keyword:
a static method is one that is not called on an instance of a class
a static attribute is one that exists only once for all instances of a class
a static function has internal linkage
a static variable, at namespace scope, has internal linkage
a static variable, at function scope, is also called local static; it is built the first time the execution flow pass through its definition and its state is then preserved between calls to the function it belongs to
Of all these uses, a single one can be (in effect) implicit: a const or constexpr variable at namespace scope has internal linkage (as if it were static) unless another storage qualifier is used (such as extern).
§3.5 Program and linkage [basic.link]
3/ A name having namespace scope (3.3.6) has internal linkage if it is the name of
a variable, function or function template that is explicitly declared static; or,
a variable that is explicitly declared const or constexpr and neither explicitly declared extern nor previously declared to have external linkage; or
a data member of an anonymous union.
Do note that const or constexpr thus never imply static, but in the specific case highlighted in the second bullet point for variables declared at namespace scope have the same effect on linkage.
No in both the cases the objects will be created upon every call.
Why should the compiler provide staticness implicitly in the first case ?
In the case of function A(), will vectorA only be constructed once in the program, no matter how many A() calls?
No. If you want only one construction of vectorA, you need to declare it as static:
const static Vector3D vectorA(1.0f);
I believe the compiler implicitly declares it static yes?
Don't assume that.

Global scope vs global namespace

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.

C++ : what is :: for?

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."