My question is about using one class's variables in another class in a different file.
I have a class in Mabbs Input.h which looks like this:
class fileParameters{
public:
static int numImageRows;
static int imageRowLength;
private:
int numRows=0;
};
int numImageRows = 640;
int imageRowLength = 480;
I would like to use the variables numImageRows and imageRowLength in a separate file called Image Centering.cpp. I am aware that I need to put it in the header Image Centering.h, which I have done.
This is the code I have in Image Centering.h:
class imageCenteringParameters{
public:
static int numImageRows;
static int imageRowLength;
private:
int imageArray[numImageRows][imageRowLength];
};
I have 2 questions:
a.) Is this the correct way to ensure I can use the variables from the class fileParameters in Mabbs Input.h in any other file? If so, is there a better/ more efficient way? If not, how would I go about fixing this, and what is good website to learn this from?
b.) It says that the fields in imageArray must have a constant size. I thought they would since they are declared in Mabbs Input.h. How would I go about fixing this, but more importantly, what does this mean?
Classes in C++ can be extended, creating new classes which retain characteristics of the base class. This process, known as inheritance, involves a base class and a derived class: The derived class inherits the members of the base class, on top of which it can add its own members.
The inheritance relationship of two classes is declared in the derived class. Derived classes definitions use the following syntax:
class derived_class_name: public base_class_name
{ /*...*/ };
The const qualifier explicitly declares a data object as something that cannot be changed. Its value is set at initialization. You cannot use const data objects in expressions requiring a modifiable lvalue. For example, a const data object cannot appear on the lefthand side of an assignment statement.
Variables definition using const type qualifier use the following syntax:
const type variable_name = initial_and_only_value;
For further reading making a constant array in C++.
Related
I just wrote a class with some static data members, but now I am getting errors about "undefined references". Why doesn't this work? What am I doing wrong?
_(Note: This is meant to be an entry to [Stack Overflow's C++ FAQ](https://stackoverflow.com/questions/tagged/c++-faq). If you want to critique the idea of providing an FAQ in this form, then [the posting on meta that started all this](https://meta.stackexchange.com/questions/68647/setting-up-a-faq-for-the-c-tag) would be the place to do that. Answers to that question are monitored in the [C++ chatroom](https://chat.stackoverflow.com/rooms/10/c-lounge), where the FAQ idea started out in the first place, so your answer is very likely to get read by those who came up with the idea.)_
To understand this, you should have a good understanding of compiling and linking, and the differences between declarations and definitions.
Consider the following class:
//In header file
class Example {
static bool exampleStaticMember;
};
Here, exampleStaticMember is declared but not defined. This means that if exampleStaticMember is used in a way that means that it must have an address then there must be a separate definition for it. In general, no declaration of a static data member in a class definition is a definition of that member.
The required declaration is usually put in the cpp file which contains the other definitions for the members of the class. It must be in the same namespace as the class definition. The definition typically looks like:
//In source file:
//This may optionally have an initialiser (eg "= true")
bool Example::exampleStaticMember;
The definition can be put in any cpp file, but it should not be put in the header with the class, because that would be likely to break the One Definition Rule.
As a special case, if the static member variable is an const integral or enumeration type then it can have an initialiser in the class definition:
//In header file
class Example {
static const int initialised = 15;
};
In this case, the definition in the cpp file is still required, but it is not allowed to have an initialiser:
//In source file
//Note: no initialiser!
const int Example::initialised;
Static members that have been initialised like this can be used in constant expressions.
Templates
For a static data member of a template, things are slightly different. The static member should be defined in the header along with the rest of the class:
//In header file
template<typename T>
class Example {
static int exampleInt;
static T exampleT;
}
template<typename T> int Example<T>::exampleInt;
template<typename T> T Example<T>::exampleT;
This works because there is a specific exception to the One Definition Rule for static data members of class templates.
Other uses of static
When the static keyword is applied to functions and objects that are not in a class scope it can take on a very different meaning.
When applied to objects in a function scope, it declares an object that is initialised in the first execution of the function and that subsequently keeps its value between function calls.
When applied to objects or functions at namespace scope (outside of any class or function definition), it declares objects or functions with internal linkage. This usage is deprecated for objects, as the unnamed-namespace provides a better alternative.
You have to instantiate static members defined in a header in a .cpp file. For example:
// foo.h
class foo {
static int X;
};
// foo.cpp
#include "foo.h"
int foo::X = 0;
For constants of a class, should I use class scope static const, or file scope const?
For example:
// .h
class C {
private:
static const int some_constant_c;
}
// .cc
const C::some_constant_c = 10;
vs.
// .h
class C {
}
// .cc
const some_constant_c = 10;
To me, the former one have better semantic meaning that the constant is of a certain class, but the latter one have the advantage not exposing constants to header file.
==============
One follow up question on this:
What if I want my constants be accessed by subclasses. Make sense to put static const in protected? Example follows:
// .h
class C {
protected:
static const int some_constant_c;
}
It's a matter of personal preference, of course. Trying not to expose class internals in the header file is a ship that has most definitely sailed in C++... between member variables and private member functions, it's just not practical to keep implementation details out of the header (unless you're using the pImpl idiom).
If all you want is to hide the value of the constant, note that you can put the initializer in the source file instead.
If you do implement the constants as globals in the source file, use an anonymous namespace to keep them from causing linker collisions.
I'd prefer 2nd variant, provided the const in the 1st case is private.
Why should one pollute the class declaration with redundant information?
Consider, you are implementing a protocol parser, with many many constants. How will the class declaration look like?
Another issue is, why should you type the name of the const twice? I try to keep definition and initialization as close as possible.
Just an opinion.
I'm fairly inexperienced with C++ and I'm trying to understand what this code does.
template <typename T>
class System : public BaseSystem
{
[..]
private:
static SystemType sysType;
};
Outside the class definition there is something like this:
template <typename T>
SystemType System<T>::sysType= IDGen<BaseSystem>::GenerateNextID();
Is this setting the sysType field in the System class to a new ID? But since the sysType field is private how is it able to access it? Also, why is the type included before the assignment?
If I wanted to change a field I would do something like field = newvalue; however this Foo field = newvalue; seems like it's creating a new field of type Foo and then assigning it.
Can anyone explain what is that line of code doing?
It is not an "assignment". It is the definition of the static data member sysType of your class. In your case the syntax contains quite a bit of template-related stuff, but the immediate matter in question has nothing to do with templates at all. A minimalistic example of the same thing might look as follows
class SomeClass {
...
static int i; // declaration of `SomeClass::i`
...
};
int SomeClass::i = 42; // definition of `SomeClass::i`
All static members of the class have to be defined somewhere (with some exceptions for constant integral members). What you have inside the class is a mere declaration.
So, one more time: every time you declare a static data member in your class, you will have to define it somewhere outside of the class, following the general One Definition Rule for data objects with external linkage, i.e. you have to define in your program once and only once.
In your case the definition includes an initializer. The = is a part of the initialization syntax. It has nothing to do with assignment.
The access protection does not come into play here at all. In this case you are not accessing a class member, you are defining it. Just like you define private member functions outside of the class, you define private static members outside of the class.
I have started reading C++ and I have a question about classes and member variables of type Enum and Struct. Where should I declare Enums/Structs so that I can use them as member variables when I separate header and implementation file? And also, how can I make a final member variable in a C++ class? I am just getting compilation error when adding const int myTest as a member variable, where should I initialize them?
The header file is like a person saying 'I can do this, that and the other' - so put declarations into it - enums, structs, class declarations, constants, ...
The implementation file is like a person saying 'I can do this and this is how I can do it' - it produces a recipe - Actual machine code for the CPU to crunch.
const says - do not change me. To intialise in a class you need:
class X
{
private:
const int y;
public:
X() : y(5) {}
};
for example. If you are learning about C++ const is a very useful tool to prevent you making a multitude of errors.
the simplest solution is to simple declare the enums & structs directly before the class they are a member of:
struct Gizmo
{
int n_;
};
class Foo
{
public:
Gizmo gizmo_;
};
If Gizmo is logically coupled to Foo (eg, if you would never use a Gizmo outside the context of using a Foo), it might also make sense to make Gizmo a nested class:
class Foo
{
public:
struct Gizmo
{
int n_;
};
Gizmo gizmo_;
};
If you want to instantiate a Gizmo declared this way, you can resolve the scope yourself:
Foo::Gizmo gizmo;
Finally, if Gizmo and Foo are not logically coupled, and you might use Gizmos all over the place without needing a Foo, then it probably belongs in its own header file.
gizmo.h
struct Gizmo
{
int n_;
};
foo.h
#include "gizmo.h"
class Foo
{
public:
Gizmo gizmo_;
};
Where should I declare Enums/Structs so that I can use them as member variables when I separate header and implementation file?
You must declare them before their use, that is. before the declaration of the member in the class of their type. Either:
you define them in their own header file and #include that file in your class' header file (before the declaration of your class)
or you define them just before your class
or you define them in your class before the members
I am just getting compilation error when adding const int myTest as a member variable, where should I initialize them?
In the constructor, using initializers. Ie.:
Clazz::Clazz() : my_const_var(0) { ... }
If you're going to add an enum or struct as a member variable of the class, the definition of the enum or struct must be complete before you declare the member. This can either be inside the class, outside of the class but coming before it in the .h header, or in a different .h header that is included before or within the current one.
There shouldn't be any problem declaring a member variable as const, but it places a restriction on how it must be initialized. You must do it in the initializer list of the constructor.
MyClass::MyClass() : myTest(value)
{
}
I have noticed that some of my functions in a class are actually not accessing the object, so I made them static. Then the compiler told me that all variables they access must also be static – well, quite understandable so far. I have a bunch of string variables such as
string RE_ANY = "([^\\n]*)";
string RE_ANY_RELUCTANT = "([^\\n]*?)";
and so on in the class. I have then made them all static const because they never change. However, my program only compiles if I move them out of the class: Otherwise, MSVC++2010 complains "Only static constant integral variables may be initialized within a class".
Well that's unfortunate. Is there a workaround? I would like to leave them inside the class they belong to.
They can't be initialised inside the class, but they can be initialised outside the class, in a source file:
// inside the class
class Thing {
static string RE_ANY;
static string RE_ANY_RELUCTANT;
};
// in the source file
string Thing::RE_ANY = "([^\\n]*)";
string Thing::RE_ANY_RELUCTANT = "([^\\n]*?)";
Update
I've just noticed the first line of your question - you don't want to make those functions static, you want to make them const. Making them static means that they are no longer associated with an object (so they can't access any non-static members), and making the data static means it will be shared with all objects of this type. This may well not be what you want. Making them const simply means that they can't modify any members, but can still access them.
Mike Seymour has given you the right answer, but to add...
C++ lets you declare and define in your class body only static const integral types, as the compiler tells. So you can actually do:
class Foo
{
static const int someInt = 1;
static const short someShort = 2;
// etc.
};
And you can't do that with any other type, in that cases you should define them in your .cpp file.
Some answers including even the accepted answer seem to be a little misleading.
You don't have to
Always assign a value to static objects when initializing because that's optional.
Create another .cpp file for initializing since it can be done in the same header file.
You can even initialize a static object in the same class scope just like a normal variable using the inline keyword.
Initialize with no values in the same file
#include <string>
class A
{
static std::string str;
static int x;
};
std::string A::str;
int A::x;
Initialize with values in the same file
#include <string>
class A
{
static std::string str;
static int x;
};
std::string A::str = "SO!";
int A::x = 900;
Initialize in the same class scope using the inline keyword
#include <string>
class A
{
static inline std::string str = "SO!";
static inline int x = 900;
};
Since C++11 it can be done inside a class with constexpr.
class stat {
public:
// init inside class
static constexpr double inlineStaticVar = 22;
};
The variable can now be accessed with:
stat::inlineStaticVar
Static member variables must be declared in the class and then defined outside of it!
There's no workaround, just put their actual definition in a source file.
From your description it smells like you're not using static variables the right way. If they never change you should use constant variable instead, but your description is too generic to say something more.
Static member variables always hold the same value for any instance of your class: if you change a static variable of one object, it will change also for all the other objects (and in fact you can also access them without an instance of the class - ie: an object).
I feel it is worth adding that a static variable is not the same as a constant variable.
using a constant variable in a class
struct Foo{
const int a;
Foo(int b) : a(b){}
}
and we would declare it like like so
fooA = new Foo(5);
fooB = new Foo(10);
// fooA.a = 5;
// fooB.a = 10;
For a static variable
struct Bar{
static int a;
Foo(int b){
a = b;
}
}
Bar::a = 0; // set value for a
which is used like so
barA = new Bar(5);
barB = new Bar(10);
// barA.a = 10;
// barB.a = 10;
// Bar::a = 10;
You see what happens here. The constant variable, which is instanced along with each instance of Foo, as Foo is instanced has a separate value for each instance of Foo, and it can't be changed by Foo at all.
Where as with Bar, their is only one value for Bar::a no matter how many instances of Bar are made. They all share this value, you can also access it with their being any instances of Bar. The static variable also abides rules for public/private, so you could make it that only instances of Bar can read the value of Bar::a;
Just to add on top of the other answers. In order to initialize a complex static member, you can do it as follows:
Declare your static member as usual.
// myClass.h
class myClass
{
static complexClass s_complex;
//...
};
Make a small function to initialize your class if it's not trivial to do so. This will be called just the one time the static member is initialized. (Note that the copy constructor of complexClass will be used, so it should be well defined).
//class.cpp
#include myClass.h
complexClass initFunction()
{
complexClass c;
c.add(...);
c.compute(...);
c.sort(...);
// Etc.
return c;
}
complexClass myClass::s_complex = initFunction();
If your goal is to initialize the static variable in your header file (instead of a *.cpp file, which you may want if you are sticking to a "header only" idiom), then you can work around the initialization problem by using a template. Templated static variables can be initialized in a header, without causing multiple symbols to be defined.
See here for an example:
Static member initialization in a class template
Optionally, move all your constants to .cpp file without declaration in .h file. Use anonymous namespace to make them invisible beyond the cpp module.
// MyClass.cpp
#include "MyClass.h"
// anonymous namespace
namespace
{
string RE_ANY = "([^\\n]*)";
string RE_ANY_RELUCTANT = "([^\\n]*?)";
}
// member function (static or not)
bool MyClass::foo()
{
// logic that uses constants
return RE_ANY_RELUCTANT.size() > 0;
}