#include <iostream>
int C;
class C {
private:
int i[2];
public:
static int f() {
return sizeof(C);
}
};
int f()
{
return sizeof(C); // why the C can't be the class type C.
}
int main()
{
std::cout << "C::f() = " <<C::f() << ","
<< " ::f() = " <<::f() << std::endl;
}
The above code returns: C::f() = 8, ::f() = 4
My question is why the identifier C
inside the global function f
resolves to the object of type int
that has name C, instead of the class type C
? Does sizeof
have a specific name lookup rule?
Conclusion : From what I read in this https://stackoverflow.com/a/612476/1021388, hiding class names by function/object/enumerator names is for compatibility concerns with C. And to avoid this inadvertent hiding, one should typedef
the class to force compiler errors.
The sizeof operator applied to a type name yields the amount of memory that can be used by an object of that type, including any internal or trailing padding. The result is the total number of bytes in the array. For example, in an array with 10 elements, the size is equal to 10 times the size of a single element.
sizeof can be applied to any data-type, including primitive types such as integer and floating-point types, pointer types, or compound datatypes such as Structure, union etc. sizeof() operator is used in different way according to the operand type.
In C language, sizeof( ) is an operator. Though it looks like a function, it is an unary operator. For example in the following program, when we pass a++ to sizeof, the expression “a++” is not evaluated. However in case of functions, parameters are first evaluated, then passed to function.
It returns the size of a variable. It can be applied to any data type, float type, pointer type variables. When sizeof() is used with the data types, it simply returns the amount of memory allocated to that data type.
sizeof
isn't the key to this question. It simply happens to be something that can be used both on type name or a variable name. These rules apply to other uses of identifiers as well.
§9.1 [class.name] (c++ standard draft n3797):
- ...snip... If a class name is declared in a scope where a variable, function, or enumerator of the same name is also declared, then when both declarations are in scope, the class can be referred to only using an elaborated-type-specifier.
There is a class by the name of C
and a variable by the same name in the global scope. Therefore, the class can be referred to only using an elaborated type specifier (class C
).
Inside the definition of C
, however, the first part of that paragraph is relevant:
§9.1 [class.name]:
- A class declaration introduces the class name into the scope where it is declared and hides any class, variable, function, or other declaration of that name in an enclosing scope ...snip...
§9 [class]:
- ...snip... The class-name is also inserted into the scope of the class itself; this is known as the injected-class-name ...snip...
So, inside the scope of class C
, the injected class name hides the int C
declaration from the outer scope. Therefore you can refer to C
without elaborated type specifier. To refer to the global int C
, you could use ::C
Regarding your question, sizeof
does not have any special parsing or evaluation rules.
Consider the following:
#include <iostream>
#include <typeinfo>
int C;
class C {
public:
int i[2];
};
int main()
{
// compiles fine:
int x = C;
// prints 0:
std::cout << C << "\n";
// prints something that corresponds to "int"
// (or even "int" itself):
std::cout << typeid(C).name() << "\n";
}
In all three cases, C
is taken as the int
variable and not as the type name.
If you need a clear distinction, you can always use class C
:
#include <iostream>
#include <typeinfo>
int C;
class C {
public:
int i[2];
};
int main()
{
// prints something that corresponds to "class C"
// (or even "class C" itself):
std::cout << typeid(class C).name() << "\n";
// prints sizeof(int):
std::cout << sizeof(C) << "\n";
// prints sizeof(int) * 2:
std::cout << sizeof(class C) << "\n";
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With