Just trying to grab the concept revolving around the scope of the Class in C++. If we take an example something like:
#include <iostream>
using namespace std;
string barValue="OUTSIDE CLASS";
class foo
{
public:
void print_bar()
{
cout<<barValue<<endl;
}
};
int main()
{
foo f;
f.print_bar();
return 0;
}
I am wondering:
Is the barValue variable is in the Class scope?
Can the barValue be accepted even if it is defined in one of the included files?
Is the file and all the included files can be called as the scope of the foo Class?
I can understand that the barValue will not be considered if it is defined after the Class body. To follow up is that means all the included files comes before the Class body and in general before the current file content?
Question 1
Is the barValue variable is in the class scope?
barValue is a global variable since you have defined it outside any function and class. Therefore barValue can be used inside the class as you did.
Question 2
Can the barValue be accepted even if it is defined in one of the included files?
Yes even if barValue is defined in a header file it can be used in other files because/if it has external linkage as shown in the below example.
file.h
int barvalue = 34;//barvalue has external linkage
main.cpp
#include <iostream>
#include "file.h"
int main()
{
std::cout<<barvalue<<std::endl;//prints 34
return 0;
}
Question 3
Is the file and all the included files can be called as the scope of the foo class?
No
Question 4
I can understand that the barValue will not be considered if it is defined after the class body. To follow up is that means all the included files comes before the Class body and in general before the current file content?
You should clarify this question more because i think it is not clear what your are asking here but i will try to answer what i understand from your question.
If you define barValue after the class foo definition then the program will not work because since you have defined it after the class definition, therefore it has not been defined/declared at the point when you write cout<<barValue<<endl; which is what the error says as shown below:
#include <iostream>
using namespace std;
class foo
{
public:
void print_bar()
{
cout<<barValue<<endl;//error: ‘barValue’ was not declared in this scope
}
};
int main()
{
foo f;
f.print_bar();
return 0;
}
string barValue="OUTSIDE CLASS";
Related
So I have a file called test.cpp
class Entity
{
int c = 0;
int b = 0;
int d = 5;
};
And then another called main.cpp
#include<iostream>
#include<vector>
#include<algorithm>
class Entity
{
int a = 5;
int b = 0;
};
int main()
{
}
Why does this link and work just fine? Doesn't the linker see that there are 2 classes with the same name and different data members? Also would these be considered class definitions? If I wanna declare this class in a header file I would just do what I did here right? Even though I'm technically defining variables it's still just a class declaration right..?
It is an ill-formed program.
As the class definition has external linkage then each definition of the class shall consist of the same sequence of tokens.
On the other hand, as neither code from the translation unit test.cpp is used the linker can exclude it from the final exe file.
In one of my classes header file Lfo.h, I have a class definition where I put the member function definition out of the class (It might be better to have a separate .cpp file but it should be ok put here?):
// Lfo.h
class CLfo
{
public:
static int create (CLfo*& pCLfo);
};
int CLfo::create(CLfo *&pCLfo)
{
pCLfo = new CLfo;
return 0;
}
Then I have another class called CVibrato:
// Vibrato.h
class CVibrato
{
public:
static int create (CVibrato*& pCVibrato);
private:
CVibrato();
};
and the .cpp file (in the cpp file, I include Lfo.h because later on the vibrato class will have a lfo member but I haven't implemented right now):
// Vibrato.cpp
#include "Lfo.h"
#include "Vibrato.h"
int CVibrato::create(CVibrato *&pCVibrato)
{
pCVibrato = new CVibrato();
return 0;
}
CVibrato::CVibrato()
{
}
Then I want to create a instance of vibrato class in main()
#include "Vibrato.h"
#include "Lfo.h" // if comment this line out there will be no error, why is that?
int main()
{
CVibrato *vibrato = 0;
CVibrato::create(vibrato);
return 0;
}
However I get a 1 duplicate symbol for architecture x86_64 error. What is duplicated? It seems the reason is in Lfo.h, I put the definition of the member function outside of the class, if I put it inside, the program runs properly. But I cannot understand. In c++, aren't we allowed to do this? By the way, if one of my class (in my case vibrato) is going to have a class member of another class (in this case lfo), should I include the header file of member class in .h (vibrato.h) file or .cpp (vibrato.cpp) file?
Classes are declarations. No code is produced from a declaration. Even if you have a member function in the class, it is treated as if an inline by the compiler. Function bodies can be put in a header but should always be declared as inline. The compiler may not actually inline it, but it will treat it as a single instance for code creation.
Any time you:
void function( ) { }
Code is created for that function. If a header is included more than once the compiler is told to create the code more than once. But all functions must have unique names! So you get the duplicate error. That is why code generating lines belong in the .cpp files.
'inline' tells the compiler not to create immediate code but to create the code at the usage point.
You can't put class method definition directly in a header file, unless you explicitly mark it as inline. Like the following:
// Lfo.h
class CLfo
{
public:
inline static int create (CLfo*& pCLfo);
};
int CLfo::create(CLfo *&pCLfo)
{
pCLfo = new CLfo;
return 0;
}
Or,
// Lfo.h
class CLfo
{
public:
static int create (CLfo*& pCLfo);
};
inline int CLfo::create(CLfo *&pCLfo)
{
pCLfo = new CLfo;
return 0;
}
If I have a class similar to this :
//body.h
class Body
{
static int i;//line 1
};
int Body::i=2;/line 2
and a class like this:
//ball.h
#include <body.h>
//line 3
class Ball:public Body
{
int f();
};
and in ball.cpp :
int Ball::f()
{
return 1;
}
this results in multiple definition of i.
I tried putting extern in line1,line2 and defining it in line 3 and still having the same error, I also searched the web, most of the results I find talks about a variable declared solely(not in a class) while I have a static class variable.
I understood that extern is opposite to static but making i extern in line1 didn't help, also I saw many questions in SO , this talks about namespaces which I don't want, this doesn't address my issue.
As A note, there is no body.cpp, there are classes other than Ball that inherits body and there is main.cpp which will access all the children classes.
So what to do to be able to use Body::i outside body.h ?
PS
all classes are surrounded in header guards .
Create another translation unit Body.cpp and move the definition there
int Body::i=2;
Even with header guards, as you mention to have them, the definition appears in multiple translation units, hence the multiple definition error.
In your particular case the static class member is a primitive, and can be initialized at the point of declaration alternatively:
class Body {
static int i = 2;
};
You should not define the static member in the header. You need to make a source (.cpp) file for it:
body.h (declare statics but don't define)
class Body
{
static int i; // only declare
};
// int Body::i=2; // do not define it here
body.cpp (define statics here)
#include "body.h"
int Body::i = 2; // now we define it
I am facing a problem when implementing some new code to an existing library. This library already references a class with a name say 'foo'. The same name is used as a namespace in the other header file which has to be included to implement the new functionality. Since both the header files are a part of legacy code libraries I cannot amend them. So here I am looking for any way so as to avoid the Compiler Error (C2757: a symbol with this name already exists and therefore this name cannot be used as a namespace name). I am not sure whether it is possible or not. Hence, Any help shall be appreciated. Thanks
For clarity here is the sample code illustration for the issue:
HeaderA.h
class foo
{}
HeaderB.h
namespace foo
{
class ABC{}
}
HeaderC.h
#include <HeaderA.h>
#include <HeaderB.h>
using namespace foo;
class Toimplement{
ABC a; //Throws Error C2757
}
You can try the following workaround:
namespace bar {
#include "HeaderA.h"
}
#include "HeaderB.h"
...
bar::foo fooObject;
foo::ABC abcObject;
Include one of header file in new namespace.
namespace headerb {
#include <HeaderB.h>
}
...
...
headerb::ABC a1;
ABC b2;
In your example, the simplest approach is to not include HeaderA.h in HeaderC.h. The class foo isn't needed in Toimplement.
so let's assume you need the visibility of both files, and you want to link to the symbols included by HeaderA:
// header a
class FOO {};
// followed by a file with your declarations/disambiguators
typedef FOO wwlib_FOO;
// header b
namespace FOO {class ABC {};}
// followed by a file with your declarations/disambiguators
namespace vvlib_FOO = FOO;
// and finally usage
using namespace FOO; // note: using `using` is a good way to introduce complications like this one
void fn() {
class FOO t;
wwlib_FOO t2(t);
vvlib_FOO::ABC abc;
...
the namespace trick won't work, apart from very very simple cases (unless it's entirely templates or inlines, which is very unusual). you'll just end up with duplicated code, classes that you can't pass around, and missing references at link-time.
I have a little class called Stuff that I want to store things in. These things are a list of type int. Throughout my code in whatever classes I use I want to be able to access these things inside the Stuff class.
Main.cpp:
#include "Stuff.h"
int main()
{
Stuff::things.push_back(123);
return 0;
}
Stuff.h:
#include <list>
class Stuff
{
public:
static list<int> things;
};
but I get some build errors with this code:
error LNK2001: unresolved external symbol "public: static class std::list<int,class std::allocator<int> > Stuff::things" (?things#Stuff##2V?$list#HV?$allocator#H#std###std##A) Main.obj CSandbox
fatal error LNK1120: 1 unresolved externals C:\Stuff\Projects\CSandbox\Debug\CSandbox.exe CSandbox
I am a C# guy, and I am trying to learn C++ for a side project. I think that I don't understand how C++ treats static members. So please explain what I have got wrong here.
Mentioning a static member in a class declaration is a declaration only. You must include one definition of the static member for the linker to hook everything up properly. Normally you would include something like the following in a Stuff.cpp file:
#include "Stuff.h"
list<int> Stuff::things;
Be sure to include Stuff.cpp in your program along with Main.cpp.
Static data members have to be defined outside class declarations, much like methods.
For example:
class X {
public:
static int i;
};
Must also have the following:
int X::i = 0; // definition outside class declaration
Stuff::things is only declared, but it is not defined.
please use:
// Stuff.cpp
#include "Stuff.h"
std::list<int> Stuff::things;
Added: it is also a good practice to protect your header files against multiple inclusion:
// Stuff.h
#ifndef STUFF_H_
#define STUFF_H_
#include <list>
class Stuff {
public:
static std::list<int> things;
};
#endif
Just For your Information, why this works is that in C++ all global variables (including static global) are created before the execution of the main function begins.
Static member have to be declared in the class but defined in the unit (cpp file) where it is really located.
The only exception is in case the class is template: in this case you have to define the member outside the class, but you have to provide it too with the class declaration, in the header file.