Mutable Variable in Class -- Issue - c++

#include <iostream>
using std::cout;
class Test
{
public:
int x;
mutable int y;
Test()
{
x = 4; y = 10;
}
static void disp(int);
};
void Test::disp(int a)
{
y=a;
cout<<y;
}
int main()
{
const Test t1;
Test::disp(30);
t1.y = 20;
cout << t1.y;
return 0;
}
I am getting error with in the constructor:
void Test::disp(int a)
{
y=a;
cout<<y;
}
I don't understand why this is not working because y is mutable and its already updated successfully within constructor Test() but when its coming to disp(). its shows error..
I have also checked with some other examples also . So I came to know you can update a mutable variable once only. If you try to update it more then one time it shows an error. Can anyone explain why this happening or reason behind it?

Your problem doesn't have anything to do with mutable. You are trying to modify a non-static class member from a static method, which is not allowed. In your example it makes little sense to have the Test::disp method static in the first place.
You also seem to have misunderstood the meaning of mutable. It doesn't make members of a const object non-read-only. It makes it possible for const methods to write to members. Your code updated to show what mutable does:
#include <iostream>
using std::cout;
class Test
{
public:
int x;
mutable int y;
Test()
{
x = 4; y = 10;
}
void disp(int) const; // Notice the const
};
void Test::disp(int a) const
{
y=a; // ::disp can write to y because y is mutable
cout<<y;
}
int main()
{
Test t1;
t1.disp(30);
t1.y = 20;
cout << t1.y;
return 0;
}
And yes, there is no limit to the number of times a mutable variable can be written, just to be clear.

Related

set default parameter to a member variable [duplicate]

This question already has answers here:
How to use a member variable as a default argument in C++?
(4 answers)
Closed 1 year ago.
I tried to set a default parameter to a member variable, it gave me this bug.
[cquery] invalid use of non-static data member 'num'
code
#include <iostream>
class Test{
private:
int val = 0;
public:
void print_num(int num = val){
std::cout << num << '\n';
}
}
int main(){
Test test;
test.print_num();
return 0;
}
Despite it being quite obvious what this would mean, you just can’t. The usual workaround is to provide an overload that (implicitly) uses this to get the member value.
In order to set a default value for a function parameter to a class member, the member must be static.
Citing the documentation,
Non-static class members are not allowed in default arguments
However, given the context of your code sample I doubt this is what you want to do (as every instance of Test class will point to the same val. Citing the docs:
Static members of a class are not associated with the objects of the class: they are independent variables
If you make val static in your example, and have multiple instances of Test in use by your code, you can (and very likely will) have some unexpected behavior. Consider:
#include <iostream>
class Test{
private:
static int val;
public:
void print_num(int num = val){
std::cout << num << '\n';
}
void set_val(int num) {
val = num;
}
}
int Test::val = 0;
int main(){
Test test1;
test1.set_val(1);
Test test2;
test2.set_val(2);
test1.print_num(); // results in "2"
return 0;
}
A better alternative would be to pass a pointer to your function like this:
#include <iostream>
class Test{
private:
int val = 0;
public:
void print_num(int* numptr = nullptr){
int num = (numptr ? *numptr : val);
std::cout << num << '\n';
}
}
int main(){
Test test;
test.print_num();
return 0;
}
Or, as described by Davis Herring, use an overload:
#include <iostream>
class Test{
private:
int val = 0;
public:
void print_num(int num){
std::cout << num << '\n';
}
void print_num() {
return print_num(val); // return is irrelevant here, but my preferred coding style
}
}
int main(){
Test test;
test.print_num();
return 0;
}
Edited to reflect the comment and example.
Your function definition doesn't actually know what val is because it doesn't actually live inside of your class. The compiler is actually making a function that contains your class as a parameter and abstracts away all of that. You'll want to set num to val within the function body.

Non-const lambda capture in const method

#include <iostream>
#include <functional>
class Blub {
public:
int i = 0;
std::function<void()> create() const {
return [this]() {
this->i = 100;
};
}
};
int main() {
Blub blub = Blub();
blub.create()();
std::cout << blub.i << std::endl;
return 0;
}
I know that this is captured as const inside the lambda, because the method is marked const.
Is there still a way, aside from removing the constness of the method, to archive that i can modify member variables inside the lambda function?
Adding mutable keyword is not working.
You can declare the member variable i as mutable, so that it could change even if the object is declared as const:
class Blub {
public:
mutable int i = 0;
// ^^^^^^^
std::function<void()> create() const {
return [this]() {
this->i = 100;
};
}
};
Live here.
You can do the following workaround:
class Blub {
public:
int i = 0;
std::function<void()> create() const {
return [my_this=const_cast<Blub*>(this)]() {
my_this->i = 100;
};
}
};
but it is misleading to change a data member in a function which is actually marked as const so I wouldn't suggest designing your class in that way.
Check it out live.
N.B. It is worth to mention that const_cast is safe to use only if it's used for casting a variable that was originally non-const. If the variable is originally const, using const_cast could result in Undefined Behavior. So, in the following code (which the OP provided):
int main() {
Blub blub = Blub();
blub.create()();
std::cout << blub.i << std::endl;
return 0;
}
it is safe to use const_cast because object is originally made non-const. However, if we make it const like in the following code:
int main() {
const Blub blub = Blub();
blub.create()();
std::cout << blub.i << std::endl;
return 0;
}
it will result in an Undefined Behavior.

C++: Changing Class Member Values From Functions

I apologize for posting such a basic question, but I cant find a decent answer as to why this doesn't work, and how to get it to work.
I have simplified my issue here:
#include <iostream>
using namespace std;
class A {
public:
int x;
};
void otherFunction() {
A A;
cout<<"X: "<<A.x<<endl;
}
int main(){
A A;
A.x = 5;
otherFunction();
return 0;
}
Do the class members become constant after constructing?
How do I expand the scope of changes done to the class?
Are structs limited in this way?
Thank you in advance for answers.
You are not getting the expected output because in otherFunction() you are creating a new object of type A for which you have not assigned a value before!
Read up on scope of a variable in C++ to learn more
Try running the code given below, you should get the output as 5.
#include <iostream>
using namespace std;
class A {
public:
int x;
};
void otherFunction(A a) {
cout << "X: " << a.x << endl;
}
int main(){
A a;
a.x = 5;
otherFunction(a);
return 0;
}
Alternatively you can do this, which is considered a good practice in OOP
class A{
private:
int x;
public:
void update(int newx){
x = newx;
}
int getX(){
return x;
}
};
int main(){
A a;
a.update(5);
cout << a.getX() << endl;
return 0;
}
It is doing what it is supposed to do.
You are creating a new object A inside the function otherFunction, this new object will be local to the function.
Print the the value of A.x after the call of function otherFunction in the main , you will see the the value of A.x has changed.
The variable A in main is not the same as the variable A in otherFunction, so they won't have the same value.
One way to give otherFunction access to the value of A in main is to pass it in as a parameter. For example:
void otherFunction(A p) {
cout<<"X: "<<p.x<<endl;
}
int main(){
A a;
a.x = 5;
otherFunction(a);
return 0;
}
I have changed the names of the variables to make it a bit more clear. a is in main, and a copy of a is passed into otherFunction. That copy is called p in otherFunction. Chnages that otherFunction makes to p will not cause any change to a.If you want to do that, you would need to pass by reference, which is probably a topic a bit further along than you are now.

stopping a `const` member from being edited under another alias

I have a class with an const abstract member. Since it is abstract, the object must reside in a higher scope. However, it may be edited in this higher scope. I have made this MWE, and added comments explaining what I am trying to achieve (.i.e. I know this does NOT achieve what I want).
Besides commenting the hell out of it, what can be done to stop the user from editing the object. Preferably, an idiot proof method (optimally, compile error)
#include <iostream>
class Foo
{
private:
const int * p_abstract_const;
//int my application this is a pointer to abstract object
public:
Foo(const int * p_new_concrete_const)
{
p_abstract_const = p_new_concrete_const;
}
void printX()
{
std::cout << *p_abstract_const << std::endl;
}
};
int main()
{
int concrete_nonconst = 666;
Foo foo(&concrete_nonconst); // I want this NOT to compile
//const int concrete_const(1);
//Foo foo(&concrete_const); // only this should compile
foo.printX();
concrete_nonconst=999; // so that this will NOT be possible
foo.printX();
}
You can make your non-const int* constructor private without providing an implementation:
class Foo
{
private:
const int * p_abstract_const;
//int my application this is a pointer to abstract object
Foo(int * p_new_concrete_const);
public:
Foo(const int * p_new_concrete_const)
{
p_abstract_const = p_new_concrete_const;
}
void printX()
{
std::cout << *p_abstract_const << std::endl;
}
};
int main()
{
int concrete_nonconst = 666;
Foo foo(&concrete_nonconst); // This won't compile
const int concrete_const(1);
Foo foo(&concrete_const); // But this will
foo.printX();
concrete_nonconst=999; // so that this will NOT be possible
foo.printX();
}

using function object though function pointer is required

I have to use some legacy code expecting a function pointer, let's say:
void LEGACY_CODE(int(*)(int))
{
//...
}
However the functionality I have is within a functor:
struct X
{
Y member;
X(Y y) : member(y)
{}
int operator()(int)
{
//...
}
};
How should I modify/wrap class X so that LEGACY_CODE can access the functionality within X::operator()(int) ?
Your question makes no sense. Whose operator do you want to call?
X a, b, c;
LEGACY_CODE(???); // what -- a(), b(), or c()?
So, in short, you cannot. The member function X::operator() is not a property of the class alone, but rather it is tied to an object instance of type X.
Search this site for "member function" and "callback" to get an idea of the spectrum of possible approaches for related problems.
The crudest, and quite possibly not-safe-for-use, workaround to providing a free function would go like this:
X * current_X; // ugh, a global
int dispatch(int n) { current_X->operator()(n); }
int main()
{
X a;
current_X = &a;
LEGACY_CODE(dispatch);
}
You can see where this is going...
A simple wrapper function looks like:
int wrapperfunction(int i) {
Functor f(params);
return f(i);
}
If you want to be able to pass the parameters to the functor itself, the simplest way is to sneak them in using (brr) a global variable:
Functor functorForWrapperfunction;
int wrapperfunction(int i) {
functorForWrapperfunction(i);
}
// ...
void clientCode() {
functorForWrapperfunction = Functor(a,b,c);
legacyCode(wrapperfunction);
}
You can wrap it with a class with a static method and a static member if you want.
Here's one compile-time solution. Depending on what you need, this might be a too limited solution for you.
template<typename Func, int Param>
int wrapper(int i)
{
static Func f(Param);
return f(i);
}
A thread-safe version under the restriction that the legacy code is not called with different parameters in a thread.
IMHO, one cannot get rid of global storage.
#include <boost/thread.hpp>
#include <boost/thread/tss.hpp>
class AA
{
public:
AA (int i) : i_(i) {}
void operator()(int j) const {
static boost::mutex m; // do not garble output
boost::mutex::scoped_lock lock(m);
std::cout << " got " << j << " on thread " << i_ << std::endl;
Sleep(200); }
int i_;
};
// LEGACY
void legacy_code(void (*f)(int), int i) { (*f)(i); }
// needs some global storage through
boost::thread_specific_ptr<AA> global_ptr;
void func_of_thread(int j)
{
AA *a = global_ptr.get();
a->operator()(j);
}
void worker(int i)
{
global_ptr.reset(new AA(i));
for (int j=0; j<10; j++)
legacy_code(func_of_thread,j);
}
int main()
{
boost::thread worker1(worker,1) , worker2(worker,2);
worker1.join(); worker2.join();
return 0;
}