This question already has an answer here:
Unable to initialize private const member [duplicate]
(1 answer)
Closed 4 years ago.
Why can't I do this in C++?
struct SomeStruct
{
public:
SomeStruct(const int someInt)
{
m_someInt = someInt;
}
private:
const int m_someInt;
};
Should the private field just be a regular integer?
You're assigning someInt to m_someInt, which is illegal. But initialization is okay.
struct SomeStruct
{
public:
SomeStruct(const int someInt) : m_someInt(someInt)
{
}
private:
const int m_someInt;
};
More info: Constructors and member initializer lists
Value cannot be assigned to a const storage. It can be only initialized. In case of class member variable it would be done in initialization list.
struct SomeStruct
{
public:
SomeStruct(const int someInt) : m_someInt(someInt)
{
}
private:
const int m_someInt;
};
Sometimes in-class initialization is enough:
template <int Val>
struct SomeStruct
{
public:
private:
const int m_someInt = Val;
};
Usually confusion stems from the fact that programmer doesn't see difference between two cases:
// 1) Declaring storage of int object that initially contains value 5
int a = 5; // It's a declaration.
// 2) Declaring storage of int object that contains undetermined value
int b; // Declaration
b = 5; // Assigning a value to it. It's a statement.
In your case m_someInt = someInt; is a statement that expects lvalue before =, and m_someInt is not a legal lvalue because it is const.
Related
class Foo
{
public:
const int a;
const int* x;
int* const y;
Foo() : a{ 0 }, y{ new int(20) } {
x = new int(10);
}
};
int main()
{
Foo f;
// f.a = 100; // cannot
f.x = new int(100);
// f.y = new int(100); // cannot
}
When const int a is defined as fields of a class,
it is called a constant member. It must be initialized in the initializer list and cannot be changed afterwards.
How about const int* x (which is the same as int const* x) and int* const y? Which one should be called as a constant member? If "constant member" is defined as field that must be initialized in the initializer list and cannot be changed afterwards, then the constant member is y rather than x. Am I wrong here?
Edit
According to IntelliSense, y is a constant member.
OK. I am sure I am not wrong. I will delete this question shortly. Thank you for your participation!
The "const int* x" is a (non-const) pointer to a const int. Since x is non-const, it need not be initialized upon construction.
Here are some examples:
class C
{
public:
C() :
const_int(1),
const_int_again(2),
const_ptr_to_non_const_int(nullptr),
const_ptr_to_const_int(nullptr)
{}
private:
const int const_int;
int const const_int_again;
const int* ptr_to_const_int; // Doesn't need initialized
int const* ptr_to_const_int_again; // Doesn't need initialized
int* const const_ptr_to_non_const_int;
const int* const const_ptr_to_const_int;
int const* const const_ptr_to_const_int_again;
};
You may find the cdecl.org website helpful.
#include <iostream>
using namespace std;
class T1
{
const int t = 100;
public:
T1()
{
cout << "T1 constructor: " << t << endl;
}
};
When I am trying to initialize the const member variable t with 100. But it's giving me the following error:
test.cpp:21: error: ISO C++ forbids initialization of member âtâ
test.cpp:21: error: making âtâ static
How can I initialize a const value?
The const variable specifies whether a variable is modifiable or not. The constant value assigned will be used each time the variable is referenced. The value assigned cannot be modified during program execution.
Bjarne Stroustrup's explanation sums it up briefly:
A class is typically declared in a header file and a header file is typically included into many translation units. However, to avoid complicated linker rules, 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.
A const variable has to be declared within the class, but it cannot be defined in it. We need to define the const variable outside the class.
T1() : t( 100 ){}
Here the assignment t = 100 happens in initializer list, much before the class initilization occurs.
Well, you could make it static:
static const int t = 100;
or you could use a member initializer:
T1() : t(100)
{
// Other constructor stuff here
}
There are couple of ways to initialize the const members inside the class..
Definition of const member in general, needs initialization of the variable too..
1) Inside the class , if you want to initialize the const the syntax is like this
static const int a = 10; //at declaration
2) Second way can be
class A
{
static const int a; //declaration
};
const int A::a = 10; //defining the static member outside the class
3) Well if you don't want to initialize at declaration, then the other way is to through constructor, the variable needs to be initialized in the initialization list(not in the body of the constructor). It has to be like this
class A
{
const int b;
A(int c) : b(c) {} //const member initialized in initialization list
};
If you don't want to make the const data member in class static, You can initialize the const data member using the constructor of the class.
For example:
class Example{
const int x;
public:
Example(int n);
};
Example::Example(int n):x(n){
}
if there are multiple const data members in class you can use the following syntax to initialize the members:
Example::Example(int n, int z):x(n),someOtherConstVariable(z){}
You can upgrade your compiler to support C++11 and your code would work perfectly.
Use initialization list in constructor.
T1() : t( 100 )
{
}
Another solution is
class T1
{
enum
{
t = 100
};
public:
T1();
};
So t is initialised to 100 and it cannot be changed and it is private.
If a member is a Array it will be a little bit complex than the normal is:
class C
{
static const int ARRAY[10];
public:
C() {}
};
const unsigned int C::ARRAY[10] = {0,1,2,3,4,5,6,7,8,9};
or
int* a = new int[N];
// fill a
class C {
const std::vector<int> v;
public:
C():v(a, a+N) {}
};
Another possible way are namespaces:
#include <iostream>
namespace mySpace {
static const int T = 100;
}
using namespace std;
class T1
{
public:
T1()
{
cout << "T1 constructor: " << mySpace::T << endl;
}
};
The disadvantage is that other classes can also use the constants if they include the header file.
This is the right way to do. You can try this code.
#include <iostream>
using namespace std;
class T1 {
const int t;
public:
T1():t(100) {
cout << "T1 constructor: " << t << endl;
}
};
int main() {
T1 obj;
return 0;
}
if you are using C++10 Compiler or below then you can not initialize the cons member at the time of declaration. So here it is must to make constructor to initialise the const data member. It is also must to use initialiser list T1():t(100) to get memory at instant.
you can add static to make possible the initialization of this class member variable.
static const int i = 100;
However, this is not always a good practice to use inside class declaration, because all objects instacied from that class will shares the same static variable which is stored in internal memory outside of the scope memory of instantiated objects.
In C++ you cannot initialize any variables directly while the declaration.
For this we've to use the concept of constructors.
See this example:-
#include <iostream>
using namespace std;
class A
{
public:
const int x;
A():x(0) //initializing the value of x to 0
{
//constructor
}
};
int main()
{
A a; //creating object
cout << "Value of x:- " <<a.x<<endl;
return 0;
}
Hope it would help you!
This question already has answers here:
Const vs Static Const
(2 answers)
What is the difference between static const and const?
(4 answers)
Closed 8 years ago.
The following statements are both valid:
static const A = 2;
const B = 3;
What is the difference of declaring the first or the second?
If the static const were to be declared inside a class it'd accesible from the class and any instance of the class, so all of the would share the same value; and the const alone will be exclusive for every instance of the class.
Given the class:
class MyClass {
public:
static const int A = 2;
const int B = 4;
};
You can do this:
int main() {
printf("%d", MyClass::A);
/* Would be the same as */
MyClass obj;
printf("%d", obj.A);
/* And this would be illegal */
printf("%d", MyClass::B);
}
Check it out here on Ideone.
Static means the entire class only shares 1 const, where non-static means every instance of the class has that const individually.
Example:
class A{
static const a;
const b;
}
//Some other place:
A m;
A n;
Objects m and n have the same a, but different b.
This question already has answers here:
How does a 'const struct' differ from a 'struct'?
(5 answers)
Closed 9 years ago.
This is a rather simple question, but somehow difficult to find a simple answer for.
In C++, what is the difference between an (edit) const-modified struct variable, and a(edit:) non-const struct variable, but with the struct having all-const members? :
typedef struct mystruct {
const int x;
} t1;
const t1 s1;
vs
typedef struct {
int x;
} t2;
const t2 s2;
? (If the answer is "the same as for classes", then please either explain it for classes or link to the explanation.)
There's no such thing as a const struct. You may have seen something like this:
const struct {
int x;
} y;
This is a declaration of a variable y with struct type. The variable y is const, not the struct. You can think of it as similar to:
struct mystruct {
int x;
};
const mystruct y;
without giving the struct type a name.
There's effectively very little difference between the two objects a and b below:
struct A
{
int x, y;
};
struct B
{
const int x, y;
};
const A a; // (plus initialiser)
B b; // (plus initialiser)
(You know, of course, that other instances of A may not be const-qualified and then you have an obvious difference.)
You can't access the members any differently in the one case than in the other. But:
You will have to ensure that you initialise the members, in both cases (which I haven't done here);
const-qualifiying the type (rather than the members) affects reference-binding:
void foo(A& a);
void foo(B& b);
int main()
{
const A a;
B b;
foo(a); // Error!
foo(b); // OK
}
The same is true, of course, if you use a pointer instead of a reference. The const context only spreads to calling code when it's applied to the type rather than encapsulated within the members.
Assuming
const struct mystruct1 {
int x1;
int x2;
} s1;
and
struct mystruct2 {
const int x1;
int x2;
} s2;
For s1 you should not assign values to any members.
For s2 only the member x1 should not be assigned a value. One is free to do so for x2.
To get closer to your example, one could do:
typedef const struct mystruct1 {
int x1;
int x2;
} S1;
typedef struct mystruct2 {
const int x1;
int x2;
} S2;
S1 s1;
S2 s2;
For s1 and s2 here the same rules apply as above.
Upate:
Referring your question literally (implying the corrections as by my examples), there is no practical difference between the two construct in terms constantness of the value they carry.
Suppose I have a C++ struct that has both POD and non-POD member variables:
struct Struct {
std::string String;
int Int;
};
and in order for my program to produce reproduceable behavior I want to have all member variables initialized at construction. I can use an initializer list for that:
Struct::Struct() : Int() {}
the problem is as soon as I need to change my struct and add a new POD member variable(say bool Bool) I risk forgetting to add it to the initializer list. Then the new member variable will not be value-initialized during struct construction.
Also I can't use the memset() trick:
Struct::Struct()
{
memset( this, 0, sizeof( *this ) ); //can break non-POD member variables
}
because calling memset() to overwrite already constructed non-POD member variables can break those.
Is there a way to enforce value-initialization of all POD member variables without explicitly adding their initialization in this case?
The cleanest way would be to write the auto-initialzed template class initialized<T>:
EDIT: I realize now it can be made even more flexible by allowing you to declare initialized<Struct>. This means that you can declare initialization without modifying the original Struct. The default initialization 'T()' was inspired on Prasoons answer.
template<class T>
struct initialized
{
public:
initialized()
{ value = T(); }
initialized(T t)
{ value = t; }
initialized(const initialized<T>& x)
{ value = x.value; }
T* operator &() { return &value; }
operator T&() { return value; }
private:
T value;
};
struct PodStruct
{
std::string String;
int Int;
};
struct GlorifiedPodStruct
{
std::string String;
initialized<int> Int;
};
void Test()
{
GlorifiedPodStruct s;
s.Int = 1;
int b = s.Int;
int * pointer = &s.Int;
initialized<PodStruct> s2;
}
This compiles, but may need more conversion operators, handling of keywords like volatile, etc. But you get the idea.
Linked Question here
Is there a way to enforce value-initialization of all POD member variables without explicitly adding their initialization in this case?
I am not sure whether something like that is possible [directly] or not but the following works
prasoon#prasoon-desktop ~ $ cat check.cpp && clang++ check.cpp && ./a.out
#include <iostream>
struct Struct {
std::string String;
int Int;
bool k;
// add add add
};
struct InStruct:Struct
{
InStruct():Struct(){}
};
int main()
{
InStruct i;
std::cout<< i.k << " " << i.Int << std::endl;
}
0 0
prasoon#prasoon-desktop ~ $
You can add a base struct:
struct PODStruct
{
PODStruct(unsinged int count) { memset( this, 0, count);}
};
And then your struct derived from this base struct, first place if you have more than one base structs,
struct Struct : PODStruct
{
Struct();
std::string Str;
int Int;
}
Struc::Struct() : PODStruct(sizeof(Struct))
{
}