C++ global variable that can be changed only in one method, possible? - c++

I'm looking for a way to have an int variable that persists value across method calls. From this perspective a class member will be good.
But I would like that int variable to be changed in only one particular method.
How do I make that?
I tough about
void MyClass::my_method(){
static int var = 0;
var++;
}
But, I would like var = 0; to be executed only the first time.

void my_method(){
static int var;
var++;
}
The problem here is, that
static int var;
is only visible in the local scope of my_method().
You can make it global just by definition of that variable outside of my_method():
int var;
void my_method() {
var++;
}
but var will be visible for everyone.
The better way is to encapsulate all of that into a class:
class MyClass {
public:
static void my_method() {
var++;
}
private:
static int var = 0;
};

You can use the following key access pattern:
struct Foo {
void fun1();
void fun2();
static class Var {
friend void Foo::fun1();
int i = 0;
public:
int value() const { return i; }
} var;
};
Foo::Var Foo::var;
void Foo::fun1() { var.i = 42; }
void Foo::fun2() {
// var.i = 42; // this will generate compile error cause fun2 doesn't have to var
}
Live Demo
This way only the member functions of Foo that are declared friends in wrapper class Var can change its private member variables (e.g., var.i).

var is just locally, if you want that to be 0 the first time the function returns make it initialized to -1 or if 0 is just right you are ok. As is var is only visible inside my_method so if you want that to be visible to all the class you have to put it outside and use only my_method to modify the value.

I don't have enough rep to comment yet, But you should note that Static is not equal to Constant.
Static variables maintain their value for ALL instances of a class, whereas Constant variables can have different values for each instance (object) of a class.
See this question for a more in-depth explanation.
What is the difference between a static and const variable?
To answer your question directly, you cannot have a true "Global" vairable that is only editable from one class. Instead, you should consider πάντα ῥεῖ 's answer OR wait to declare the constant until after you know the value you would like to assign to it. For instance, I want to store X+10 to a constant variable Y
int x = 5 //create variable
//Do whatever you need to do to get the value
function myFunction(){
x = x + 10;
}
const int y = x; //now Y = 15 and cannot be changed.

Related

Is this a valid workaround to avoid "invalid use of member ‘X::XX’ in static member function"?

I was working on someone else's project, and I ran into an issue where the author's static function was preventing me from doing what I wanted. I wanted the function to modify a member variable I had created, which can't happen if the object was never instantiated.
As expected, accessing Foo::number from the static function Foo::foobar() causes this error:
staticvspointer.cpp:20:5: error: invalid use of member ‘Foo::number’ in static member function
My two options are to make the variable "number" a global, or make the function not static.
int NUMBER; //this could be global, but would make the large project messy
//class has a static function
class Foo {
public:
Foo();
static int foobar();
int number;
};
//make member function not static
class Bar {
public:
Bar();
void foobar(int);
int number;
};
Foo::Foo() {
}
int Foo::foobar() {
//can't access "number = 2;" in static function.
NUMBER = 2; //CAN access global though
return 2;
}
Bar::Bar() {
}
void Bar::foobar(int number) {
this->number = number;
}
int main() {
//1.) using a static function to get 2
int a = Foo::foobar();
int b = a + 2;
//b = 4
//2.) using a pointer to get ClassName::memberVariable, and then deleting it.
Bar* bar = new Bar;
bar->foobar(2);
b = bar->number + 2;
delete bar;
//b still = 4
//3.) using a global
Foo::foobar();
b = NUMBER + 2;
//b = 4 again
return 0;
}
I assume the problems this may or may not cause are dependent on the project, but I can't think of a reason not to do this.
Is there anything wrong with method #2? Is it a proper use of pointers? Is it readable or confusing? For some reason it feels wrong to me.

Passing Objects by reference

(I did not find the answer I was looking for but I figure it out my self so I want to try answering my own Question for someone else who may have it in the future)
How can I pass an object to a non-Class function and change its data?
For example
class Foo{} has a private int x = 5 and I want to change it to 10 with out entering the changeValue function from the class directly but use a non-Class function to call this function.
So if your code looks something like this:
class Foo {
public:
void changeValue(int val) { x = val; }
private:
int x;
}
And you want to change the x outside the changeValue method, all you need to do is add function you want to change it in as a friend to Foo class. So for example, for this to work:
void g(Foo& foo) {
foo.x = 10;
}
You must add this line to your Foo class:
friend void g(Foo& foo);
Declaring something inside the class as a friend allows that function/class to access private members and methods.
Let's say we have
class Foo{
private:
int x;
public:
change(int y){
x = y;
}
}
and we want the function
void changeVal(Foo test, int num);
to change the X instead of
Foo::change(int y);
we would give our changeVal function the address of the object
int main(){
Foo test;
changeVal(&test, 5);
}
then we are going to create changeVal and make a pointer object to hold the address of our original object
void changeVal(Foo* test, int num){
...
}
and in the body we need to create a third object to take the value of the original object so we give it the address we stored in the "Foo* test" and change the value of the new object with the address of the original so we are changing the original instead of a copy
void changeVal(Foo* test, int num){
Foo test2 = &test;
test2.change(num);
}

Is it possible change value of Member variable within "const" function?

Value of constant variable can be changed through pointer tricks, but is it possible to do something like this :
class A (){
int x;
public:
void func () const {
//change value of x here
}
}
declare x mutable
class A (){
mutable int x;
public:
void func () const {
//change value of x here
}
};
You have two options:
class C
{
public:
void const_f() const
{
x = 5; // A
auto* p_this = const_cast<C*>(this); // B
p_this->y = 5;
}
private:
mutable int x; // A
int y;
};
A: declare certain members mutable.
B: const_cast to remove constness from the this pointer.
Though this is not appreciated, but C++ provides “Backdoors” which can be used to breach its own regulations, just like dirty pointer tricks. Anyway, you can easily do this by using a casted version of “This” pointer :
class A (){
int x;
public:
void func () const {
//change value of x here
A* ptr = const_cast<A*> (this);
ptr->x= 10; //Voila ! Here you go buddy
}
}
The most important thing to understand here is bitwise/physical/concrete constness and conceptual/meaningwise/logical/abstract constness.
In short:
If the function is conceptually const, make the member data mutable.
Otherwise, make the function non-const.
Just cast 'this', this would be a dirty way to implement your program, do avoid this if you are doing a project or teamwork as others would get confused by this.
class CAST_CLASS (){
int var;
public:
void change_CAST () const {
CAST_CLASS* pointer = const_cast<CAST_CLASS*> (this);
pointer->var= 10;
}};
The other answers don't mention this, but following also modifies "x" (definitely, not advisable):
class A {
int x, &y{x}, *z{&x};
public:
void func () const
{
y = 42; // x is modified now!
*z = 29; // x is modified again!!
}
};

C++ Assign a const value at run-time?

I have a constant value that never changes during run-time, but is impossible to know until run-time.
Is there a way to declare a constant (either as a member of a class or not) without defining it and also assign a computed value once (and only once) it is determined; or am I going to have to resort to a non-const declaration and use coding S & Ps (ALL_CAPS variables names, static declaration if in a class, etc.) to try and keep it from changing?
CLARIFICATION:
Though these are good answers, the real-world situation I have is more complicated:
The program has a main loop that continually runs between processing and rendering; the user can set required options and once they are set they will never change until the program is restart. An "Initialize" function is set up for anything that can be determined before the main loop, but values that are dependent on user interaction must be performed in the middle of the loop during the processing phase. (At the moment, persistent data storage techniques come to mind...)
Something like this?
const int x = calcConstant();
If it's a class member, then use the constructor initialisation list, as in Yuushi's answer.
You can define it in a struct or class and utilize an initialisation list:
#include <iostream>
struct has_const_member
{
const int x;
has_const_member(int x_)
: x(x_)
{ }
};
int main()
{
int foo = 0;
std::cin >> foo;
has_const_member h(foo);
std::cout << h.x << "\n";
return 0;
}
As a static or function-local variable:
const int x = calcConstant();
As a class member:
struct ConstContainer {
ConstContainer(int x) : x(x) {}
const int x;
};
Yes, you can make a private static singleton field with an initialization method and a gettor method. Here's an example of how to do it:
// In foo.h
class Foo
{
public:
// Caller must ensure that initializeGlobalValue
// was already called.
static int getGlobalValue() {
if (!initialized) {
... handle the error ...
}
return global_value;
}
static void initializeGlobalValue(...)
private:
static bool initialized;
static int global_value;
};
// In foo.cpp
bool Foo::initialized = false;
int Foo::global_value;
void Foo::initializeGlobalValue(...) {
if (initialized) {
...handle the error...
}
global_value = ...;
initialized = true;
}

Static function needing to deal with members of a C++ class

I have to make some kind of bridge between two pieces of software, but am facing an issue I don't know how to deal with. Hopefully someone will have interesting and (preferably) working suggestions.
Here is the background : I have a C++ software suite. I have to replace some function within a given class with another function, which is ok. The problem is that the new function calls another function which has to be static, but has to deal with members of the class. This is this second function which is making me mad.
If the function is not static I get the following error :
error: argument of type ‘void (MyClass::)(…)’ does not match ‘void (*)(…)’
If I set it to static I get either the following error :
error: cannot call member function ‘void
MyClass::MyFunction(const double *)’ without object
or
error: ‘this’ is unavailable for static member functions
depending on if I use or not the "this" keyword ("Function()" or "this->Function()").
And finally, the class object requires some arguments which I cannot pass to the static function (I cannot modify the static function prototype), which prevents me to create a new instance within the static function itself.
How would you deal with such a case with minimal rewriting ?
Edit : Ok, here is a simplified sample on what I have to do, hoping it is clear and correct :
// This function is called by another class on an instance of MyClass
MyClass::BigFunction()
{
…
// Call of a function from an external piece of code,
// which prototype I cannot change
XFunction(fcn, some more args);
…
}
// This function has to be static and I cannot change its prototype,
// for it to be passed to XFunction. XFunction makes iterations on it
// changing parameters (likelihood maximization) which do not appear
// on this sample
void MyClass::fcn(some args, typeN& result)
{
// doesn't work because fcn is static
result = SomeComputation();
// doesn't work, for the same reason
result = this->SomeComputation();
// doesn't work either, because MyClass has many parameters
// which have to be set
MyClass *tmp = new MyClass();
result = tmp->SomeComputation();
}
Pointers to non-static member functions are a bit tricky to deal with. The simplest workaround would just be to add an opaque pointer argument to your function which you can then cast as a pointer to 'this', then do what you need with it.
Here's a very simple example:
void doSomething(int (*callback)(void *usrPtr), void *usrPtr)
{
// Do stuff...
int value = callback(usrPtr);
cout << value << "\n";
}
class MyClass
{
public:
void things()
{
value_ = 42;
doSomething(myCallback, this);
}
private:
int value_;
static int myCallback(void *usrPtr)
{
MyClass *parent = static_cast<MyClass *>(usrPtr);
return parent->value_;
}
};
int main()
{
MyClass object;
object.things();
return 0;
}
In this example myCallback() can access the private value_ through the opaque pointer.
If you want a more C++-like approach you could look into using Boost.Function and Boost.Bind which allow you to pass non-static member functions as callbacks:
void doSomething(boost::function<int ()> callback)
{
// Do stuff...
int value = callback();
cout << value << "\n";
}
class MyClass
{
public:
void things()
{
value_ = 42;
doSomething(boost::bind(&MyClass::myCallback, this));
}
private:
int value_;
int myCallback()
{
return value_;
}
};
int main()
{
MyClass object;
object.things();
return 0;
}
If you really can't change the function prototype you could use a global pointer, but that opens up all sorts of issues if you will ever have more than one instance of your class. It's just generally bad practice.
class MyClass;
static MyClass *myClass;
void doSomething(int (*callback)())
{
// Do stuff...
int value = callback();
cout << value << "\n";
}
class MyClass
{
public:
void things()
{
value_ = 42;
myClass = this;
doSomething(myCallback);
}
private:
int value_;
static int myCallback()
{
return myClass->value_;
}
};
int main()
{
MyClass object;
object.things();
return 0;
}
Following spencercw's suggestion below the initial question I tried the "static member variable that you set to point to this" solution (the global variable would have been tricky and dangerous within the context of the software suite).
Actually I figured out there was already something like this implemented in the code (which I didn't write) :
static void* currentObject;
So I just used it, as
((MyClass*)currentObject)->SomeComputation();
It does work, thanks !!!
non-reentrant and non-thread-safe way is to pass "this" address using global variable.
You can move the result = SomeComputation(); out of your static function and place it in BigFunction right before your call to the static function.