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.
Related
I would like to use some comparable representation of type, which is not direct like std::is_same<> and does not use RTTI. __PRETTY_FUNCTION__ macro gives same string for 2 different classes with same name defined in different .cpp files in anonymous namespaces and comparing strings is slow.
Let's consider such a piece of code:
template<typename T>
void func() {}
int main() {
std::cout << reinterpret_cast<size_t>(&func<int>) << std::endl;
std::cout << reinterpret_cast<size_t>(&func<float>) << std::endl;
}
Is storing numeric value of pointer to specialized template function well defined behaviour? It will not be called anywhere.
Will it have same value in different .cpp files for same specialization?
Will it have same value between dynamic linked libraries - probably not?
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.
I am a little bit confused ...
Why is this allowed in C++:
static int t = 0;
class A
{
public:
A() : m(t++)
{
cout << "C:" << m << endl;
if(t >= 5)
{
A a; // <<<< ----- THIS line
throw( a);
}
}
int m;
};
But this not:
static int t = 0;
class A
{
public:
A() : m(t++)
{
cout << "C:" << m << endl;
}
A a; // <<<< ----- THIS line
int m;
};
The second one is not compiling as expected (yes, I know why it's not compiling: at that point in code the A is still incomplete) ...
But ... the first one compiles nicely (and does what it's supposed to do, ie: crashes the application on a statement like: A a[10]; ). Is the A a complete type in the constructor? Can also point me some C++ standard entries for this situation?
When you are declaring any variable, compiler should know the size of that. in case of your second example you are creating an object of A inside A so compiler will not be able to calculate the size of A to allocate memory.
Can also point me some C++ standard entries for this situation?
Yes, the draft C++ standard says a class is not completely defined until the closing }, this is in section 9.2 Class members paragraph 2:
A class is considered a completely-defined object type (3.9) (or complete type) at the closing } of the classspecifier. [...]
and all non-static data members of a class must be complete, from paragraph 9:
Non-static (9.4) data members shall not have incomplete types. In particular, a class C shall not contain a non-static member of class C, but it can contain a pointer or reference to an object of class C.
but it is considered complete within the constructor also within paragraph 2:
[...]Within the class member-specification, the class is regarded as complete within function bodies, default arguments,[...]
although static members can be incomplete, section 9.4.2 Static data members paragraph 2:
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.[...]
It also makes sense to not allow a class to contain itself since this would require infinite space since the self reference would never end, A contains A which contains A ...
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.
I was reading the C++0x FAQ by Stroustrup and got stuck with this code. Consider the following code
struct A
{
void f(double)
{
std::cout << "in double" << std::endl;
}
};
struct B : A
{
void f(int)
{
std::cout << "in int" << std::endl;
}
};
int main()
{
A a; a.f(10.10); // as expected, A.f will get called
B b; b.f(10.10); // This calls b.f and we lose the .10 here
return 0;
}
My understanding was when a type is inherited, all protected and public members will be accessible from the derived class. But according to this example, it looks like I am wrong. I was expecting the b.f will call base classes f. I got the expected result by changing the derived class like
struct B : A
{
using A::f;
void f(int)
{
std::cout << "in int" << std::endl;
}
};
Questions
Why was it not working in the first code?
Which section in the C++ standard describes all these scoping rules?
Its because A::f is "hidden" rather than "overloaded" or "overridden". Refer:
http://www.parashift.com/c++-faq-lite/strange-inheritance.html#faq-23.9
The first code works as c++ is designed to work.
Overloading resolution follows a very complicated set of rules. From Stroustrup's c++ bible 15.2.2 "[A]mbiguities between functions from different base classes are not resolved based on argument types."
He goes on to explain the use of "using" as you have described.
This was a design decision in the language.
I tend to follow the Stroustrup book rather than the standard, but I'm sure it is in there.
[Edit]
Here it is (from the standard):
Chapter 13
When two or more different declarations are specified for a single name in the same scope, that name is said to be
overloaded.
And then:
13.2 Declaration matching
1 Two function declarations of the same name refer to the same function if they are in the same scope and have equivalent parameter declarations (13.1). A function member of a derived class is not in the same scope as a function member of
the same name in a base class.
Search for overload resolution. A similar, but not identical question.
In C++, there is no overloading across scopes, scoped in derived classes are not an exception.
(According to The C++ Programming Language)
For more info, check out http://www.research.att.com/~bs/bs_faq2.html#overloadderived
In the first case, the base class method 'f' is hidden by the derived class method. In C++ there is no overloading across scopes; that is why it is not called. The C++ standard explains all the member name lookup rules in the section 10.2 Member name lookup [class.member.lookup].
HTH
The first version of code should really call B::f. You re-define the symbol "f" in struct "B", so it hides the original symbol "f" from struct "A". It is not an overload, as it may seem.
Whenever compiler meets b.f(), it searches the "B" struct for a symbol "f". It is present there, so the compiler decides to call B::f(int), converting double to int. It sees no need to scan the parent class for a more suitable function...
Yet, when you add "using A::f", it is an explict directive for the compiler to scan a parent class for symbol "f". Now, B class has two overloaded functions: for int and for double.
I also believe, that you could write b.A::f() without using "using" directive in the original example...