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.
Related
As the question states i'm trying to initalize a static class member variable using this same class's static member function but at a chosen time during runtime.
The is that the copy constructor for GameDataLocalResource is implicitly deleted because one of its fields has no copy assignement operator. So I tried to define the copy constructor but i'm still getting the same error at compilation.
How should i handle the problem. Please keep in mind i'm beginner in C++.
I looked at many thread on how to initialize a static member variable at runtime but none seems to fit my situation.
//*.h file
class GameDataResource
{
private:
static GameDataLocalResource local_resource;
public:
static void initializeLocalResource();
static GameDataLocalResource getLocalResource();
}
//*.cpp file
void GameDataResource::initializeLocalResources()
{
GameDataResource::local_resource = GameDataLocalResource();
}
GameDataLocalResource GameDataResource::getLocalResources()
{
return GameDataResource::local_resource;
}
//main.cpp
int main(int argc, char *argv[])
{
...
GameDataResource::initializeLocalResources();
qDebug() << GameDataResource::getLocalResources().getLoadingPercentage();
...
}
I expect to get the value of loading percentage but instead i get:
copy assignment operator of 'GameDataLocalResource' is implicitly deleted because field '****' has no copy assignment operator
Hello and welcome to C++ and stackoverflow. Since you are new and trying to understand the concepts of something being static there are two versions. You can read up about them from these links:
Storage Class Specifiers: cppreference:storage duration
Static Class Members: cppreference:static members
Since your question involves class members, you can focus more on the later.
How does static-members work? They do not belong to an object, they can be considered incomplete until a definition is encountered. The static keyword for class members can only be used during the declaration. The initialization of a class's static-member must be defined outside of the class.
Here is a simple example of static member initialization:
SomeClass.h
class Foo {
public:
static int bar;
int x;
void someFunc();
};
Here when the class's cpp file is compiled Foo::bar has static duration and internal linkage. The static member has no association to the object of Foo but can be accessed by the class's this pointer for example:
SomeClass.cpp
int Foo::bar = 0;
void Foo::someFunc() {
this->x = 5; // okay
this->bar = 9; // okay as an instance of this object can access `bar`
// since all instances share this static member
// there is only ever one instance of `Foo::bar` in memory
}
To show that it has no association to the actual instance or an object of type Foo we can see this from the example below.
SomeOtherClassOrFunction
{
Foo f;
f.a = 5; // okay as long as `a` is public
f.bar = 9; // same as above `bar` is shared across all instances of Foo
// Accessing bar we do not need an object we can do it as such:
std::cout << Foo::bar << '\n'; // Should print 9.
}
Now that you have a general understanding of static member variables static functions follow similar rules except for the rules that govern how their address can be stored in a pointer, but that is beyond the scope of this topic. The only major difference is static member functions can be accessed by the this-pointer but have no association to that object as they are static functions.
We can take the above example and remove the non static member and change the storage class of its member function and rename it.
Foo.h
#pragma once
class Foo {
public:
static int bar;
static void update(int val) { bar = val; }
};
Foo.cpp
#include "Foo.h"
int Foo::bar = 0; // default initialized
main.cpp
#include <iostream>
#include "Foo.h:"
int main() {
std::cout << "Default Foo::bar = " << Foo::bar << '\n';
Foo::update(25);
std::cout << "Updated Foo::bar = " << Foo::bar << '\n';
return 0;
}
I'm not sure if this is the exact behavior you are looking for, but this is the basic or general concepts and usages of static class members. Hopefully this will give you some insight.
GameDataLocalResource is a type and not a function which can initialize the static variable.May be this solves your problem.
So the solution I found was hinted in an answer that was deleted. Mainly I added a new member function to GameDataLOCALResource that initializes its "heavy" members.
By doing so I able to make an instance of it without loading the files.
Then a call to a static member function of GameDataResource triggers the GameDataLOCALResource instance to load the files into its member variables.
Thanks everyone !
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.
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.
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 was surprised to find that in VC++ 10, you can use a typedef to change the name of a class's constructor:
#include <iostream>
using namespace std;
class A
{
private:
typedef A alias;
public:
alias() { cout << "A ctor" << endl; }
};
int main()
{
A(); // prints "A ctor"
return 0;
}
Is this standard C++ or a Microsoft extension?
No; constructors do not have a name. You cannot take the address of a constructor or pass a function pointer around, or even just call it like a normal function. The syntax A::A() is just a special declarator syntax that allows you to declare and define the constructors, but it isn't a name.
That said, you cannot typedef objects (including function pointers) anyway, only types.
To comment on the MSVC behaviour, I quote from 12.1/3:
A typedef-name shall not be used [...] for a constructor declaration.