I used the tutorials here to learn a whole lot, thank you.
Now I have a problem:
There are two classes, one in /origin/directory1/src/class1.cc and the other in /origin/directory2/src/class2.cc which are not related to one another. Now I want to write a manager to exchange variables between the objects created in directory1 and the ones created in directory2. My idea is to create a namespace in directory1/src/my_namespace.cc with
So far so good, but now I see how my_variable is empty in an object of class2, after I call save_variable("test") in an object of class1, but not in the same object of class1.
This means that each class uses a separate namespace, right? How can I tell them to use the same?
There are two classes [...] which are not related to one another. Now I want to write a manager to exchange variables between the objects
If you want to exchange data between them, then they are related. You may be over-complicating things. Just declare the classes in header files and if one needs to store some info the other, then #include the header file and store it (directly or by calling a method):
This means that each class uses a separate namespace, right?
Hmm. You may be confusing a class definition with an instance of the class. For example, class std::string defines a variable-length string. You can create as many instances of a string as you like.
I agree with dhayden that you're probably making this too complicated, at least from your description of the problem. You don't need to concern yourself with namespaces for this. If you wish to make a member available outside the object, you do one of three things:
1. declare the member public
2. provide a get() function
3. declare a friend function (probably not recommended for this).
From your main routine, get the desired data from one object and supply it to the other. Your use of the file system is possible, but also complicates the exercise.
Hmm. You may be confusing a class definition with an instance of the class. For example, class std::string defines a variable-length string. You can create as many instances of a string as you like.
Yes you are right.
If you want to exchange data between them, then they are related. You may be over-complicating things.
I meant right now they are unrelated and work independently, but I want to relate them.
Maybe I am over-compicating, but I cannot see a way to use your solution. I try to explain a bit more: You see in directory1 some other classes will create an object of class1 and the same in directory2 with class2. Instead of tracing every instance I thought it would be easier to create a namespace working as manager.
Maybe I am to confused. If I had in
directory1/src/some_other_class1.cc
1 2 3 4 5 6
#include "class1.hh"
void some_other_class1::f(){
MyClass1 c1;
//do stuff with c1 and pass to other classes
}
but in directory2/src/some_other_class2.cc
1 2 3 4 5 6
#include "class2.hh"
void some_other_class2::g(){
MyClass2 c2;
//do completely other stuff with c2 and pass to completely other classes
}
I cannot create an instance of MyClass1 in g(), since it would not be included in the complex process in f()
As mentioned I thought using a namespace would be the easiest way to exchange information between c1 and c2 without fucking up the program. If I made a class instead of a namespace, I would not know how to get a specific object from c1 to c2 :(
for example
1 2 3 4 5 6 7 8
#include "class1.hh"
#include "mymanager.hh"
void some_other_class1::f(){
MyClass1 c1;
//do stuff with c1 and pass to other classes
MyManager m1(c1);
}
Can you give more detail? Why exactly is construction of an instance of one class affected by whether an instance of another class has been constructed? What's the actual data that needs to be shared? That strikes me as a code smell.
There is one class A, that is included in the entire calculation process, A calls B, which is a single specific problem to solve (like for example if you have these specific incoming particles and these specific outgoing ones, what are the properties of the outgoing particles?). B then calls C which does calculations with some of B's parameters. The results are fed back into B, into A. Then the next step (A2) uses the results from A on a different problem (e.g. how does a wall change the properties of the particles?).
From B I have multiple classes, but only now realized I can replace most of them with super_B (=MyClass2), which is more general, buts needs user input (GUI=MyClass1). It may smell bad, because the program was originally intended to run without the GUI, but over time the GUI proved to be very comfortable. I hope these are enough details,
I need to share strings describing a mathematical function from the GUI with super_B, then to a parser in calculator C.
Because A does not have the information from the GUI. You are right, that the distribution should be in A and I did hard code the distributions into B before, but one can work easier if one only has to change the function in one place (in my case the GUI) instead of searching the entire code for the part(s), where I used it. Example:
before:
1 2 3 4 5
void B::example(double* x, double* y, int size){
for (uint i=0;i<size;i++){
y[i]=x[i]*exp(-6*x[i]);
}
}
after:
1 2 3 4 5 6
void B::example(double* x, double* y, unsignedint size, string function){
StringCalculator calc;
for (uint i=0;i<size;i++){
y[i]=calc.calculate(function, x[i]);
}
}
where the string function is given by the GUI and StringCalculator is a calculator based on the shuntingyard algorithm, calculate evaluates function in x[i]. Right now everything works on its own and the only part left is to get this one string from the GUI to my simulation.
Then I'm convinced that the correct solution would be to pass the expression as a parameter. Your proposed solution at the top is just a hack to avoid modifying the interface.
but one can work easier if one only has to change the function in one place (in my case the GUI) instead of searching the entire code for the part(s)
Change B::example() to accept a const std::string & and recompile. The compiler will point out all the places you need to modify.
Please no. You have no idea how many classes I need to modify that way.
I tried it anyway, but I needed to stop. You see, my program is build on another physics program, which uses a special library in root. Including this one string into the constructor lead me from the afore mentioned class A out of my program into the mentioned physics program (I am no developer for this one). To avoid this one could possibly rewrite the constructor of A, but I honestly do not want to do this, because there are hanging a lot of/all other processes on this contructor and I just cannot risk changing something. If I accidentally plant a bug, it will be nearly impossible to find. I am sorry, that I am getting so afraid and irrational, but it was a lot of work and I really do not want to take risks.
"Never change a running system."
Why is it a hack and a bad idea? I thought it would function metaphorically like a router in a network instead of exchanging information like a pear-to-pear-network of >40 computers.
Why is it a hack and a bad idea? I thought it would function metaphorically like a router in a network instead of exchanging information like a pear-to-pear-network of >40 computers.
If you want to analogize, passing parameters as actual function parameters works like a network.
Passing parameters by setting globals works like adding another network to the communication protocol. You can't do anything you couldn't do before (since any network can send arbitrary information), but now the protocol is more complicated because everyone is forced to interact correctly with two networks, rather than only one.
Every time you add global state you make it more difficult to track the state of the program. A few problems off the top of my head:
* The compiler can't ensure that a function is being used correctly. Is this
example(x, y, size);
call correct, because a previous caller has already set the global, or is it incorrect, because it was supposed to be set here?
* How should the program behave when there are multiple instances of B?
* B::example() with globals can't be reentrant.
* B::example() with globals can't be called in parallel
Please no. You have no idea how many classes I need to modify that way.
The hardest part of programming is maintenance. Fixing and adding to program.
The initial design was as clever as you could possibly foresee, but now we know that it was not clever enough.
You have two options:
1. Use duct tape. It will be quick and easy, and will seemingly hold for now. Sooner or later you will be back with same two options. Every piece of tape will make the whole more fragile, more difficult to augment.
2. Thorough renovation. A lot of hard work, but the result will be more accomodating, more flexible for future additions (assuming you design wisely).
There are two classes, one in /origin/directory1/src/class1.cc and the other in /origin/directory2/src/class2.cc
Those classes could be in the same file as the main() and the situation would be identical.
The hardest part of programming is maintenance. Fixing and adding to program.
You have two options:
1. Use duct tape. It will be quick and easy, and will seemingly hold for now. Sooner or later you will be back with same two options. Every piece of tape will make the whole more fragile, more difficult to augment.
2. Thorough renovation. A lot of hard work, but the result will be more accomodating, more flexible for future additions (assuming you design wisely).
Could you give an example of what you mean? I mean, if I use duct tape now, what exactly will make the whole more fragile?
Every time you add global state you make it more difficult to track the state of the program.
* How should the program behave when there are multiple instances of B?
What if you will suddenly need more than one B?
You cannot touch the B, nor the global, for they could break (and "all the classes").
Would you clone B with rename to create suspiciously similar E, F, G, ... (with "no idea how many classes")?
How many copies?