How to modify the same variable in different classes and modify it? - c++

I have many function definitions which I have placed in different cpp files with function declarations in their respective .h files.
I have a set of a variables which I have placed in a .h file. These variables need to modified by different functions. I am using static to keep the changes from each function, but I heard it is a bad coding practice. How else to do it ? For eg -
variables.h
class variable{
static int x;
static int y;
};
function1.h
class function(){
public:
void function1();
}
similar for function 2
function 1.cpp
void function1(){
// does something with x and y (used as (variable::x=2;variable::y=3)
}
function2.cpp
void function2(){
// does something with x and y (used as variable::x+=2;variable::y+=2)
}
main.cpp
int variable::x;
int variable::y;
int main(){
obj.function1(); (obj is object of function1 class)
obj2.function2(); (obj2 is object of function2 class)
cout << variable::x << variable::y << endl;
}
I was was using different objects in different cpp files but changes in one function were not reflecting in other. How it use it please help?

You can simply move these variables into another class:
struct Shared {
int x;
int y;
};
Now you can pass an instance to this class as parameter to your function, this is called dependency injection:
void foo(Shared& shared) {
shared.x = 4;
shared.y = 2;
}
This is better because you don't have any global state anymore. You could use the function multiple times independent from each other by referencing a different instance of the Shared class.
It is very common to take this a step further by "injecting" the instance in the constructor of that class. This is helpful if the instance of that class should always reference the same instance:
struct Foo {
Shared& m_shared;
Foo(Shared& shared)
: m_shared(shared)
{
}
void foo() {
m_shared.x = 4;
m_shared.y = 2;
}
};

Yes, as you mentioned using static variable for this purpose is kind of anti-pattern. A better pattern (without knowing the background of the application) is using a composition pattern. If your functions f1() and f2() are in classes C1 and C2, you would e. g. create an additional data object D1 (with the variables in question), and inject and object of D1 in the constructor of C1 and C2, so both classes operation on a data object. There are also other solutions to this situation, but I guess thats the most general. Google for C++ Design Pattern to find more general patterns.

You can use smart pointers for global objects
struct MyGlobal
{
std::shared_ptr<Core> core;
MyGlobal(){ core=std::make_shared<Core>(); }
void changeVariableX(int X)
{
core->X = X;
}
};
You can move, copy, do whatever you want with MyGlobal instances and they still point to same core item. Just make sure all of them are populated from same instance like this:
int main()
{
MyGlobal global;
auto something = useSomeFunctionWith(global);
auto somethingElse = useAnotherFunctionWith(global);
...
// use something and somethingElse to change X, both point to the same X
}
If functions will not be thread-safe then you should add a lock-guard into changeVariableX method.

Related

Should I convert C static function to private member function or free function in unnamed namespace?

I want to update some C legacy code to C++. Suppose I had something similar to this code in C:
//my_struct.h
typedef struct myStruct {
//some members go here
} myStruct;
int f1(myStruct*);
void f2(myStruct*);
//my_struct.c
#include "my_struct.h"
static int helper(myStruct* st)
{
return 21;
}
int f1(myStruct* st)
{
return helper(st);
}
void f2(myStruct* st) {}
If I update it to the following in CPP:
//myStruct.h
struct myStruct {
int f1();
void f2();
private:
int helper();
};
//myStruct.cpp
int myStruct::f1(){
return helper();
}
void myStruct::f2(){}
int myStruct::helper(){
return 21;
}
What is the impact of converting the global static C function to a private member function in C++?
What would be the pros/cons (regarding compilation, linking, runtime) between the previous approach and the following one? I didn't use the parameter inside the function to make the example short (If it is not used I read in other questions that it should probably go to the anonymous namespace).
//myStruct.h
struct myStruct {
int f1();
void f2();
}
//myStruct.cpp
namespace{
int helper(myStruct *st){
return 21;
}
}
int myStruct::f1(){
return helper(this);
}
void myStruct::f2(){}
What is the impact of converting the global static C function to a private member function in C++?
The impact is that you've made a (private, internal) implementation detail of your module part of the (public) interface.
What would be the pros/cons (regarding compilation, linking, runtime) between the previous approach and the following one?
Cons:
you've added semantic noise to your interface
ie, there's more for clients to read and think about, even though it shouldn't affect them,
changes to internal implementation details may require all clients of the interface to recompile, instead of just re-linking
ie, if you want to change helper, that now updates the public header and causes widespread recompilation of files that shouldn't be affected
Pros:
there are none.
It's idiomatic in C++ to add implementation-file-local details like helper to the anonymous namespace.

How to declare a class member that may be one of two classes

I am working with a project that is largely not of my creation, but am tasked with adding in some functionality to it. Currently, there is a device class that has a member variable that is responsible for storing information about a storage location, setup like this:
device.hpp
class device {
public:
// Stuff
private:
// Stuff
StorageInfo storage_info_;
// Even more stuff
}
StorageInfo.hpp
class StorageInfo {
public:
void initializeStorage();
void updateStorageInfo();
int popLocation();
int peakLocation();
uint16_t totalSize();
uint16_t remainingSize();
// More declarations here
private:
//Even more stuff here
}
I am tasked with implementing a different storage option so that the two can be switched between. The information functions that this new storage option has would be the same as the initial storage option, but the implementation in retrieving that information is vastly different. In order to keep things clean and make it easier to maintain this application for years to come, they really need to be defined in two different files. However, this creates an issue inside of device.cpp, and in every single other file that calls the StorageInfo class. If I create two separate member variables, one for each type of storage, then not only will I need to insert a million different ifelse statements, but I have the potential to run into initialization issues in the constructors. What I would instead like to do is have one member variable that has the potential to hold either storage option class. Something like this:
StorageInfoA.hpp
class StorageInfoA: StorageInfo {
public:
void initializeStorage();
void updateStorageInfo();
int popLocation();
int peakLocation();
uint16_t totalSize();
uint16_t remainingSize();
// More declarations here
private:
//Even more stuff here
}
StorageInfoB.hpp
class StorageInfoB: StorageInfo {
public:
void initializeStorage();
void updateStorageInfo();
int popLocation();
int peakLocation();
uint16_t totalSize();
uint16_t remainingSize();
// More declarations here
private:
//Even more stuff here
}
device.hpp
class device {
public:
// Stuff
private:
// Stuff
StorageInfo storage_info_;
// Even more stuff
}
device.cpp
//Somewhere in the constructor of device.cpp
if(save_to_cache){
storage_info_ = StorageInfoA();
} else {
storage_info_ = StorageInfoB();
}
// Then, these types of calls would return the correct implementation without further ifelse calls
storage_info_.updateStorageInfo();
However, I know that cpp absolutely hates anything with dynamic typing, so I don't really know how to implement this. Is this kind of thing even possible? If not, does anyone know of a similar way to implement this that does work with cpp's typing rules?
You are on the right track, but you have to learn how to use polymorphism. In your example, you need the following fixes:
In the base class, make all functions virtual, and add a virtual
destructor:
class StorageInfo {
public:
virtual ~StorageInfo(){}
virtual void initializeStorage();
//...
};
Make your inheritance public:
class StorageInfoA: public StorageInfo {
Instead of holding StorageInfo by value, hold it in a smart pointer:
class device {
private:
std::unique_ptr<StorageInfo> storage_info_;
};
device constructor will look like
//Somewhere in the constructor of device.cpp
if(save_to_cache){
storage_info_ = std::make_unique<StorageInfoA>();
} else {
storage_info_ = std::make_unique<StorageInfoB>();
}
Finally, you will use it like an ordinary pointer:
storage_info_->updateStorageInfo();

Can a C++ class's default value be changed at runtime?

In C++ is it possible to change the default values of a class so that all future objects made of that class will have the values specified?
I am trying to make a class that is user-defined at run time that should function nearly identical to other child of the same parent class, but I am struggling with a way to have the same format constructor exist across both. The only way I can think to properly funnel the correct information to every new object is to have either the class type be always treated differently on creation (always put in the user inputs into the constructor) or have the class's object behavior on creation change to default to the inputs defined.
Edit: To better explain the issue and address the XY problem possibility here is the scenario:
General Program:
I want to have the user first define a custom shape by providing a name and the number of lines that define it. The user then can add triangles, squares and the custom shape to their "cart". Each custom shape is the same shape that they specified at the start, the user does not change it during the program. The program could then return general information such as the number of members of a specific type that exists or the total number of lines in the cart.
There is a parent class:
Class Shape
member numLines, name;
And three classes are children of Shape:
Class Triangle
overwritten numLines = 3, name = "triangle";
...
Class userShape
overwritten numline = ????, name = ????;
When I create methods for the cart that interact with "shape" objects I would like to be able to have the same code across the board for creating additional objects, instead of needing to treat the userShape's constructor differently.
From the answers I have received, the static type seems to best fit the user-setting of the default values but I am entirely open to better ways to implement something like this.
Just because you can, doesn't mean you should. Now that I got that out of the way, here's how:
#include <iostream>
struct C {
static int default_val;
C(int i = default_val) {
std::cout << i << '\n';
}
};
int C::default_val = 0;
int main() {
C c;
C::default_val = 1;
C c2;
return 0;
}
A default argument to a function doesn't have to be a constant expression, it just has to be "available" at every place the function is called. And a static variable is just that.
It also doesn't have to be accessible at the call site. So if you want the class to control it, but not have it be modifiable from outside the class, you can make it private.
I would recommend following the next pattern:
Run your application
Read/Load the configuration
Create a factory for that object from that configuration
Use the factory to create more instances of the same object throught the lifetime of your application
For example:
struct Object {
Object(int x, int y) : _x(x), _y(y) {}
int _x, _y;
};
struct DynamicFactory {
DynamicFactory(int x, int y) : _x(x), _y(y) {}
std::shared_ptr<Object> generate() { return std::make_shared<Object>(_x, _y); }
int _x, _y;
};
int main(){
// Load configuration
// Initialize dynamic factory using configuration
DynamicFactory factory(1, 3);
// Generate objects
auto obj1 = factory.generate();
auto obj2 = factory.generate();
return 0;
}
Try to use static members so these are shared across the objects.

C++ Can't access public variable between classes

I've been trying desperately to get share a public variable between two classes in C++, but I can't seem to get the hang of it. I've tried getters and setters and calling it directly as a static variable but nothing.
This is what I've tried:
DataGrabber.h
#pragma once
class DataGrabber {
public:
static float temp;
void readProcess(){
temp = 1.2;
}
}
Particle.h
#pragma once
class Particle {
public:
void update() {
float x = DataGrabber::temp;
}
AND THEN THIS:
DataGrabber.h
#pragma once
class DataGrabber {
public:
float temp;
float get(){return temp;}
void readProcess(){
temp = 1.2;
}
}
Particle.h
#pragma once
class Particle {
public:
void update() {
float x = DataGrabber.get();
}
They are both being #include in another main header, testApp.h.
What is the exact problem? How do you use these classes?
Regardless, there are several problems with your getter code.
First, why do you use getter if you make the variable public? If you are going for this design, you should hide the variable as private, to protect it from direct modification.
Second, if it is a simple member variable, you should access it through an object that you pass to your function:
void update(DataGrabber& grabber) {
float x = grabber.get();
}
In this case, you would have to create this object in your main code, which you have not shown.
If you want to use a static variable instead, take a look at a Singleton pattern, but I would advise against it unless there are no better options for your exact problem.
Finally, you should #include all direct dependencies in your header files. Your Particle depends on DataGrabber, so you should include its header from Particle.h. Or, at least, you should add a forward declaration.

Structure of program

I have few files:
main.cpp:
int main{
...
while(1){
...
draw();
...
}
...
return 0;
}
and draw.cpp:
I want to see objects and all manipulations here.
I cant make objects local to draw(), because draw() is inside loop,
so I will get many object constructor/destructor calls - so they are global. Also
I ve made init block to prevent unnecessary calls/assignments
draw.cpp:
Object A, B;
int initialized = 0;
void draw(){
if(!initialized){
A.initialization;
B.initialization;
initialized = 1;
}
A.move(1,1);
B.rotate(45);
}
It works, but Im looking for better way to organize my code
Added:
Thanks for answers, looks like I have to read something about pattern designs
Here's steps to make it work better:
Add a struct containing all your objects near main().
pass it to draw(MyStruct &s); via reference parameter.
you're done.
Option 1
Define a new Class called Draw and put the attributes into it. You need to modify main and draw files for this. With this you can avoid declaring anything global
Option 2
Define a class within draw.cpp called draw and add your current global variables as static member variables. Initialize and use them using static functions. With this you dont have to change main.
This design technique is called Singleton (one of the design patterns)
Example code
draw.cpp
class Draw
{
public:
object A, B;
static void init()
{
// init A
// init B
isInitialized = 1;
}
static int isInitialized;
static Object & getA()
{
if(isInitialized == 0)
{
init();
}
return A;
}
// similarly B
};