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.
Related
There are many references about compilation/linking process, but I am interested in a more concrete problem: compilation of a class.
The question arises because in general it is necessary to know things before you can use. For example: you can not call the function if it has not previously been declared.
In classes, it is not done in the same way. You can use a member before it appears. What the compiler does? Does the standard says something about a previous stage of compilation?
To be more specific, the following example shows how we can use members defined below.
#include <iostream>
class EvenOdd {
public:
EvenOdd(): value(0) {}
void assignEven(unsigned v) {
if (v>0 && v%2==1) {
std::cout << "Wrong call... is odd" << std::endl;
assignOdd(v);
}
else {
std::cout << "Right..." << v << " is Even" << std::endl;
value= v;
}
}
void assignOdd(unsigned v) {
if (v>0 && v%2==0) {
std::cout << "Wrong call... is even" << std::endl;
assignEven(v);
}
else {
std::cout << "Right..." << v << " is Odd" << std::endl;
value= v;
}
}
private:
unsigned value;
};
int main()
{
EvenOdd a;
std::cout << "Do it right..." << std::endl;
a.assignEven(2);
std::cout << "doing it wrong..." << std::endl;
a.assignEven(3);
}
We could also add further questions about inline functions, as may be defined after the point of call and the compiler can resolve without problems. I guess the answer is related.
UPDATE: I know the compilation/linkage has several steps. On the other hand, if the compiler accepts calling a function defined bellow is due that the compiler has analized the code in some sense. The question is ¿which kind of previous stage is done before? Moreover... in which part of the standard we find something related to use a member defined bellow?
To know how the compiler works is very interesting because it has to know details about the function bellow (at least, the header) that seems to correspond actually to compile. Even the data member has to be compiled because you have to relate its type in the context of the function above
It works like the code is reordered but it is not consistent with the example above because both function members call each other. It is like reordering data members and header of functions could be the code that is considered by the compiler.
The standard says
A class is considered a completely-defined object type (3.9) (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, exception-specifications, and default member initializers (including such things in nested classes). Otherwise it is regarded as incomplete within its own class member-specification.
This in particular means that a member function body may refer to class members declared below it. The standard doesn't care how implementations achieve this. One possible method would be to postpone semantic analysis of member function bodies and other elements specified above until the closing brace of the class is seen.
Functions within classes can access and modify (unless the function is constant) data members without declaring them, because the data members are already declared in the class. In your response to why function do not need declaration in class.
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.
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.
As we know,It is possible to initialize integral const static members inside the class structure.This is useful when the constant is used in the class structure after the initialization.For example,it can be used as the size of an int array.
Look the code following:
class MyClass{
static const int num = 100;
int elems[num];
...
};
But we still have to define the member num outside the class definition:
const int MyClass::num;
I don't know why we have to do like this.
Could someone tell me why?
Thanks a lot.
In addition,I write the following code:
#include <iostream>
using namespace std;
class MyClass{
public:
MyClass()
{
cout << "instruct class MyClass!" << endl;
}
static const int num = 100;
int elems[num];
};
//const int MyClass::num;
int main()
{
MyClass a;
const int *b = &(a.num);
cout << "&(a.num): " << &(a.num) << endl;
cout << "a.num: " << a.num << endl;
cout << "*b: " << *b << endl;
}
It runs well on Visual Studio 2008:
But I have removed the code that definite the member num outside the class.
I am very confused.Could someone interpret it for me?
The initialization in the class is mainly used to obtain a constant expression. For this only the value matters. Once you take the address of the object or bind it to a reference, the compiler needs a location for the object as well. This is effectively what the definition provides.
You would need to define the static constant num outside the class in a cpp file only if your code takes it's address.This is known as an Out-of-class definition.
If your code does not take address of num, then the In-class Initialization would just work fine.
Rationale:
Bjarne states:
"C++ requires that every object has a unique definition. That rule would be broken if C++ allowed in-class definition of entities that needed to be stored in memory as objects."
Note that only static const integers can be treated as compile time constants. The compiler knows that the integer value will not change anytime and hence it can apply its own magic and apply optimizations, the compiler simply inlines such class members i.e, they are not stored in memory anymore, As the need of being stored in memory is removed, it gives such variables the exception to the above rule mentioned by Bjarne.
Even if static const integral values can have In-Class Initialization, taking address of such variables is not allowed. One can take the address of a static member if (and only if) it has an out-of-class definition because then the compiler needs to place them in memory.
I've just come across the following code:
#include <iostream>
static class Foo
{
public:
Foo()
{
std::cout << "HELLO" << std::endl;
}
void foo()
{
std::cout << "in foo" << std::endl;
}
}
blah;
int main()
{
std::cout << "exiting" << std::endl;
blah.foo();
return 0;
}
I haven't seen the above method of definining a variable before - the class definition is done inline with the variable definition. It reminds me of anonymous classes in Java. What is this called, and is it in the C++ standard?
Thanks
Taras
It's quite standard to define a class (or struct, perfectly equivalent except that the default is public instead of private) and declare a variable of its type (or pointer to such a variable, etc) -- it was OK in C (with struct, but as I already mentioned C++'s class, save for public vs private, is the same thing as struct) and C++ mostly maintains upwards compatibility with (ISO-1989) C. Never heard it called by any special name.