#include <stdio.h>
#include <iostream>
using namespace std;
int val = 100;
//cout<<val<<endl; //this is not valid.
int main(){
int val=100; //why this is valid?
return 0;
}
I found out these two things in the above code:
cout<<val<<endl; is not valid outside the main function body. Why is that?
I think the two vals are all defined in the namespace std. But how come they are both valid?
cout<<val<<endl; is not valid outside the main function body. Why is that?
Because the standard says that expression statements can only be in block scope.
can I have operations outside a function body in c++?
You can't have expression statements outside a function.
However, declaration statements can have sub-expressions that have side-effects such as cout<<val<<endl (note the lack of semicolon) in which case those expressions will be executed during initialisation of whatever was declared. Neil Butterworth shows an example of this in their answer.
I think the two vals are all defined in the namespace std
You think wrong. Neither is declared in the std namespace.
One val is declared in the global namespace, while the other is declared in the function scope. Declaring one variable in a nested scope within potential scope of another vairable with the same name is called shadowing i.e. val in the block scope shadows val in the namespace scope.
void main()
This is also not valid. main must return int.
You can initialise things, possibly via function calls, so you could say something like:
ostream & os = cout<< 42 <<endl;
but the utility of this is not obvious, and you would possibly run into problems with the order of instantiation of objects like cout.
What you cannot do is write code such as:
x = x + 1;
for ( int y = 0; y < 10; y++ ) {}
outside of a function - that's the way the language is defined.
And in your code neither val is in the std namespace, and it would be illegal to try to place them there. You need to read up on scope.
Related
Code
#include <iostream>
namespace myspace
{
int x;
}
myspace::x=3; // This line is giving error.
int main()
{
myspace::x=5;
return 0;
}
Output
Error: C++ requires a type specifier for all declarations
So why line myspace::x=3; giving error that C++ requires a type specifier for all declarations ?
The statement
myspace::x=3;
isn't an initialization, it's a plain assignment. It's no different from the
myspace::x=5;
you have inside the main function.
Any statement that isn't a declaration or a definition can't be outside functions.
If you want to initialize the variable, do it at the definition:
namespace myspace
{
int x = 3;
}
You provided a definition upon first declaring the variable. And as others noted myspace::x=3; constitutes an assignment expression at namespace scope, which is not allowed.
If you want to declare the variable without defining it, you need to be explicit and specify it's an extern declaration.
namespace myspace
{
extern int x;
}
The definition would still need the type specifier (as all definitions do), but it will look somewhat like what you imagined
int myspace::x = 3;
While all of this is fine and dandy, global variables (the mutable, run-time external kind) are a code smell. So best not to get in the habit of using them.
when I was studying a book on C++, I came across this.
if we declare a class,
class student {public:
void func(int v1,int v2)
{
//some code
}
//some members.
};
and use a function with same name out of the class (non-member function) like,
void func(int x,inty)
and If I wish to call this non-member function in the member function of the above declared class, the syntax would be,
//inside the member function...
::func(x,y);
}
correct me if I am wrong.otherwise,
assuming I wrote
using namespace std;
in the beginning of the program, Is the below code equivalent to previous one?
//inside the member function
std::func(x,y);
}
and, does the answer change if I use a different namespace other than std?? ie,
provided I use,
using namespace abc
are the following declarations
abc::func(x,y)
and,
::func(x,y)
absolutely equivalent under any conditions or do they change under specific conditions??
Thank you.
in the beginning of the program, Is the below code equivalent to previous one?
//inside the member function
std::func(x,y);
No it isn't. Because you preform a qualified name lookup. It means you specify exactly in what namespace func is to be defined. std::func, if it exists, still belongs the the std namespace, not the global one.
A using namespace directive only makes identifiers available to unqualified name lookup, where it's up to the compiler to figure it out. This point is quite intricate, I know, but it's the reason namespaces can be considered useful.
The problem kicks in when you collide the names.
Do not do using namespace std;, since it can cause collision problem.
These code are identical:
using namespace std;
sort(params...); // Omitted, this will call std::sort
std::sort(params...);
And even if you are using namespace std, std::sort calls the same functions as long as std::std doesn't exist (and defining it from user side is illegal code).
However, abc::func() is not identical to ::func(). :: in the beginning means root namespace, which is the most outside namespace. There's no ambiguity or implicit filling in this case.
The using namespace directive allows your code to use stuff that is in the specified namespace. You can even have several of them:
using namespace x;
using namespace y;
This means that a function call like func() will call the function whose code resides either in x or in y namespace (or, in fact, in the global namespace).
If your code looks like this
using namespace x;
using namespace y;
void func(int, int) {... code ...}
then the func function goes in the global namespace, not in the x or y namespace. That is, ::func refers to this function, while x::func and y::func don't.
To put your code (class, function, etc) in a namespace, use this code:
namespace x
{
void func(int, int) {... code ...}
class student
{
void func(int, int) {... code ...}
};
}
Then, if you want to call the func that is outside your class, you can use x::func() or ::x::func(), but cannot use ::func().
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.
My code is like below, when I compile it , I receive this error :
two.cpp:5: error: expected constructor, destructor, or type conversion before '=
' token
#include <iostream>
using namespace std;
namespace a1{
int a=3;
a=4;
}
int main(){
cout << a1::a<<endl;
}
I encountered this problem when I defined a namespace in two files, in the second file, I can't assign a value to a variable which defined in the first file.
I am learning Beginning ANSI C++ , and can't find any information about this in the book.
The purpose of namespaces is to avoid conflicting names. So surround your variable and class declarations with namespaces. But namespaces by themselves don't provide the scaffolding for running code. What is going on with your a=4; statement ? Where is that supposed to execute ? You need to put it in a function or method, not in a namespace.
You can have declarations (which include that you can have definitions) at namespace scope, e.g.
int a = 3;
But you can not have non-declaration statements at namespace scope.
For example, an assignment such as
a = 4;
is not a declaration: it purely asks for an effect.
However, you can put that in the body of a function, e.g. in main.
Cheers & hth.,
Does your second file knows about the definition of int a; ? Namespaces don't magically work like in some other languages, you still have to include a header file containing the definition of your int a at the other file, or at list define it as external.
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'.