How to share parameters around a class - C++ - c++

I have a class which I intend to use for performing calculations. I declare one static object of the class elsewhere which I use to obtain results. The class has one public function apart from the constructor.
public:
double getProbability(PlayerStats &p1, PlayerStats &p2, Score &score);
As you can see, I have three objects as input parameters. My class then has two private functions which are called from getProbability(). One requires p1 and p2, the other requires all three of the parameters
My question is this. Is it better to pass these objects as parameters to the function or is it better to create private member variables and use these.
So for example
double MyClass::getProbability(PlayerStats &p1, PlayerStats &p2, Score &score){
otherFunction(p1,p2);
anotherFunction(p1,p2,score);
....
}
or
double MyClass::getProbability(PlayerStats &p1, PlayerStats &p2, Score &score){
this->p1 = p1;
this->p2 = p2;
this->score = score;
otherFunction(); //use member variables in these functions
anotherFunction();
....
}

It's better to pass them as parameters, as they don't really represent class state and storing them as members will probably be more performance costly than simply continuing to pass around the references.
But it doesn't really look like your class has any state at all, which leads me to believe all of these methods should be free-functions in a suitable namespace rather than members of a class (perhaps you come from a Java background?).

I prefer passing the parameter to the private functions. As far as your class may be access by multiple concurrent threads, it is better to send each data to its related function.

You should pass the arguments directly to your other methods. Even if other functions used them it would be very confusing because nothing in the function signature indicates that those arguments would be kept around.
If you need some of these parameters in other functions and those parameters remain the same through several calls, you could refactor your class. It would take the ones which stay the same in the constructor and then function calls just pass in the ones which will change. It really depends on the needs of your application to determine whether this is a better approach.

Related

Initialize member functions via constructor

Perhaps I am way out of left field with this question, but is it possible to define a member function via the constructor?
In my case, I am trying to write a class to perform robust model fitting (using RANSAC). I want this to be generalizable to different types of models. For example, I could use this to determine an estimate of a plane to a set of 3D points. Or, perhaps I could determine a transformation between two sets of points. In these two examples, there might need to be different error functions and different fitting functions. Instead of using a class, a static function call might look like
model = estimate(data, &fittingFunc, &errorFunc);
I'm wondering if I can have member instance for those modular functions?
Something like
class Estimator
{
private:
// estimation params
double errorFunc(std::vector<dtype>, double threshold); // Leave this unimplemented
double fittingFunc(std::vector<dtype>, Parameters p); // Leave this unimplemented
public:
Estimator(void (*fittingFunc(std::vector<dtype>, Parameters), void (*errorFunc(std::vector<dtype>, double));
dtype estimate(data); // Estimates model of type dtype. Gets implemented
};
Estimator::Estimator(void (*fittingFunc(std::vector<dtype>, Parameters), void (*errorFunc(std::vector<dtype>, double))
{
fittingFunc = fittingFunc;
errorFunc = errorFunc;
}
I imagine I have bastardized the proper syntax in my example, but I hope the question is clear. Basically I am asking: Can the constructor accept function pointers as arguments and assign them to be the implementation of member functions?
Secondly, even if this is possible, is it considered bad form?
UPDATE: If it helps, here is MATLAB code for robust estimation that has this sort of generalizable structure I'm hoping to replicate in C++
Can the constructor accept function pointers as arguments and assign them to be the implementation of member functions?
No. Not as member functions. But you can certainly have public member function pointers:
class Estimator
{
public:
double (*errorFunc)(std::vector<dtype>, double threshold);
double (*fittingFunc)(std::vector<dtype>, Parameters p);
public:
Estimator(void (*fittingFunc(std::vector<dtype>, Parameters), void (*errorFunc(std::vector<dtype>, double))
: errorFunc(errorFunc)
, fittingFunc(fittingFunc)
{ }
dtype estimate(data);
};
For a nicer (or safer) interface, you can make the function pointers private and have a public member function which simply invokes them.
More generally, if you're okay with the overhead, you can have members of type std::function<double(std::vector<dtype>, double)> and std::function<double(std::vector<dtype>, Parameters)> and then you can use a wider variety of callables (function pointers, but also lambdas, bound member functions, etc.)
Yes you can provide the algorithm for your fitting and error function. You could do it using pointer to function. And there is a better solution, in the standard header you will find the template std::function which can be constructed with pointer to function but also with functors or lambda expressions.
Your class would be something like this:
#include <functional>
class Estimator
{
private:
// estimation params
using error_func_type = std::function<double(std::vector<dtype>,double)>;
using fitting_func_type = std::function<double(std::vector<dtype>,Parameters p)>;
fitting_func_type fittingFunc;
error_func_type errorFunc;
public:
Estimator(fitting_funct_type fit, error_funct_type err)
:fittingFunc(fit),errorFunc(err){}
dtype estimate(data); // Estimates model of type dtype. Gets implemented
};

Best practice to pass many variables

Let's say I have a class Character: it holds many private variables such as positionX, PositionY, Atk, Def, Agi, Velocity and have to pass it to a function which processes and changes this Character variables.
Since it has so many variables, how do I pass these variables? Should I make getter and setter for each variable? What is the best practice regarding this?
I'm thinking about making a struct class that holds all those variables, so I can just pass that struct class, but I don't know if it's a good practice.
If you pass just the struct it will be copied. Good practice is to either pass it in as a reference or as a const reference, or even as a shared_ptr
void foo(const MyStruct& ms);
void foo(MyStruct& ms);
void foo(std::shared_ptr<MyStruct> ms);
If your function modifies private variables, then the function should probably be a member function.
If that is not appropriate, then you could declare the function a friend of the class.
If you have lots of functions that can't be members but need to access the member variables, and you don't need the encapsulation, then consider making the members public.

"Addition" of two classes

I've been doing some dynamical system simulations in a rather crude functional way and am currently trying to figure out what can cpp objects bring to my code. More specifically, I was thinking about the following construction:
I would like to specify the dynamical system by an abstract class, say "DynSys", with a purely virtual method specifying the dynamics (say "energy" and others). Once I derive two concrete classes from DynSys, I would like to do a "superposition" of their instances in the sense of creation of a new DynSys object that returns an addition of the two respective dynamical member functions. Is this possible? E.G.:
DynamicHole Blackhole; // DynSys derived
DynamicDisc Disc; // DynSys as well
vector state; // eg a dynamical array of numbers
Blackhole.energy(state); // returns A(state)
Disc.energy(state); // returns B(state)
??class?? HoleDisc = DynamicAddition(&Blackhole,&Disc); // is a DynSys
HoleDisc.energy(state); // returns A(state)+B(state)
The pointer to a DynSys object is passed to the simulation itself, so it is important for the result to be a DynSys object.
I saw some constructions using the "+" operator or befriending to add the parameters of the class. However, the problem here seems to be the fact that the addition process involving method addition would need to define a completely new concrete class.
I see a rather inelegant workaround by defining the "core" functions A(state,parameters), B(state,parameters) separately and then defining the superposition class by hand. I have quite a lot of superpositions to make, so I wondered whether there was a better way to do this.
If I understand correctly, when you "add" to DynSys together you want to create some aggregation. Here is a pseudocode that could be adapted to your needs:
class DynSysGroup : public DynSys
{
DynSys& m_a;
DynSys& m_b;
public:
DynSysGroup(DynSys& a, DynSys& b) : m_a(a), m_b(b) { }
// I'm guessing the signature of energy()...
void energy(vector& v)
{
// Get A(state) with m_a
// Get B(state) with m_b
// Do A(state) + B(state)
}
}
And your line above
??class?? HoleDisc = DynamicAddition(&Blackhole,&Disc); // is a DynSys
would become
DynSysGroup HoleDisc(Blackhole, Disc);
Of course, with reference like m_a and m_b you need to make sure you don't get dangling reference. Maybe you'll need to use smart pointers like std::shared_ptr.
Side note: you may want to look into std::valarray and change the way energy() works: instead of taking a vector as parameter, you could simply return it (it if fits your design, of course).
std::valarray DynSys::energy() const { return ...; }

Benefits of Static Functions for Class Constructions

I have seen code like this, so I'm trying to find the reason.
What's the main reason for having static functions that act as constructors, instead of having actual constructors?
I mean something like:
class MyClass
{
public:
static MyClass CreateFrom( bar );
static MyClass CreateFrom( foo );
...
}
instead of:
class MyClass
{
public:
MyClass( bar );
MyClass( foo );
...
}
This is called the "named constructor idiom".
It's typically used when:
You have a lot of ctors with similar enough enough parameter lists that overloaded ctors would be confusing (e.g., different mixtures of integer and floating point numbers, so 1, 1.0, 1 is supposed to mean something different from 1, 1, 1.0).
You have two different sources that both provide the input as the same type. For example, let's assume you wanted to convert a distance on the surface of the earth into the angle subtended between points that distance apart -- but you might want to supply the distance in either miles or kilometers, either of which would be represented as a double.
In this case a single angle(double dist) can't distinguish between input in kilometer vs. miles, but: angle_from_miles and angle_from_kilomters can do that quite easily.
They are called Named Constructors.
The are basically used when you want to construct an object which requires to pass a particular set of parameters but internally you need to construct the object differently.
For example you have a class like:
class AREA
{
double area;
AREA(int x);
};
//how will you construct the object differently in case of circle and square??
For this purpose, we have named constructors which help to create a relevant object.
So we may create 2 static methods inside the class as:
static AREA square(int x)
{ return AREA(x*x); }
and
static AREA circle(int x)
{ return AREA(x*x*3.14); } //or a more accurate PI value
Thus, we may call the relevant static function to return the object initialized with the required area.
NOTE: These are static as while creating an object for a particular class you shouldn't be requiring an object to do so.
Check THIS for more details.
The most obvious benefits are:
It's easy to specify the implementation which constructs the instance at the callsite, when multiple constructors are provided. This makes it easier for the class to provide multiple variants.
These variants may also have different names, but identical parameter lists (or parameter lists which the compiler may call out as ambiguous when determining which to choose).
It helps you because you can read which constructor your implementation calls -- at the callsite.
Another reason is that it is easier in some cases to initialize the class within a function body, rather than using an initialization list.

Map functions of a class

Before I was trying to map my classes and namespaces, by using static calls I succeded and now I need to map the functions of my classes because they will be used dynamically.
Firstly I was thinking to hardcode in the constructor so I can assign a std:map with the string of the name of function pointing to the function itself.
for example:
class A{
int B(){
return 1;
}
};
int main(){
A *a = new A();
vector<string, int (*)()> vec;
vector["A.B"] = a.B;
}
By that I have mapped the function B on A class, I know that I only mapped the function the instance and thats B is not static to be globally mapped.
But thats what I need, at somepoint someone will give me a string and I must call the right function of an instance of a class.
My question is if I only can do that by hardcoding at the constructor, since this is a instance scope we are talking or if there is somehow a way to do this in the declaration of the function, like here for namespaces and classes:
Somehow register my classes in a list
If I understand you correctly, you want your map to store a pointer that can be used to call a member function on an instance, the value being chosen from the map at run time. I'm going to assume that this is the right thing to do, and that there isn't a simpler way to solve the same problem. Quite often when you end up in strange C++ backwaters it's a sign that you need to look again at the problem you think you have, and see whether this is the only way to solve it.
The problem with using an ordinary function pointer is that a non-static member function is not an ordinary function. Suppose you could point to a member function with an ordinary function pointer, what would happen when you dereferenced that pointer and called the function? The member function needs an object to operate on, and the syntax doesn't provide a way to pass this object in.
You need a pointer to member, which is a slightly obscure feature with relatively tricky syntax. While an ordinary pointer abstracts an object, a pointer to member abstracts a member on a class; the pointer specifies which class member should be called, but not which object to obtain the member from (that will be specified when the pointer is used). We can use it something like this:
class B;
class A
{
B some_function()
{ /* ... */ }
};
B (A::* myval)() = A::some_function;
Here myval is a variable that indicates one of the members of class A, in this case the member some_function (though it could point to any other member of A of the same type). We can pass myval round wherever we want (e.g. storing it in an STL container, as in your example) and then when we want to call the function, we specify the instance it should be called on in order to locate the function:
A some_a;
B newly_created_b = (some_a.*myval)();
This works for a particular case, but it won't solve your general issue, because member pointers contain the class they refer to as part of the definition. That is, the following two variables are of entirely different types:
B (Foo::* first_variable)() = Foo::some_function;
B (Bar::* second_variable)() = Bar::some_function;
Even though both functions can produce a B when called without arguments, the two values operate on different classes and therefore you can't assign a value of one type to a variable of the other type. This of course rules out storing these different types in a single STL container.
If you're committed to storing these in a container, you'll have to go with a functor-based solution like Charles Salvia proposes.
If I understand you correctly, you're going to have a class like:
struct Foo
{
int bar();
};
And the user will input a string like "Foo::bar", and from that string you need to call the member function Foo::bar?
If so, it's rather awkward to code a flexible solution in C++, due to the static type system. You can use an std::map where the key is a string, and the value is a member function pointer, (or std::mem_fun_t object), but this will only work on a single class, and only on member functions with the same signature.
You could do something like:
#include <iostream>
#include <map>
#include <functional>
struct Foo
{
int bar() { std::cout << "Called Foo::bar!" << std::endl; }
};
int main()
{
std::map<std::string, std::mem_fun_t<int, Foo> > m;
m.insert(std::make_pair("Foo::bar", std::mem_fun(&Foo::bar)));
Foo f;
std::map<std::string, std::mem_fun_t<int, Foo> >::iterator it = m.find("Foo::bar");
std::mem_fun_t<int, Foo> mf = it->second;
mf(&f); // calls Foo::bar
}
just found(using google) a topic to the same question I had with an answer.
What is the simplest way to create and call dynamically a class method in C++?
I didn't try it yet but makes sense, I will ask again later if it doesn't work
ty!
Joe
I must call the right function of an instance of a class.
You need to call a specific method on an existing instance, or you need to create an instance of the appropriate type and call the method?
If it's the former, then you need a std::map or similar that lets you look up instances from their names.
If it's the latter, that's basically what serialization frameworks need to do in order to create the correct type of object when de-serializing, the object that knows how to read the next bit of data. You might take a look at how the Boost serialization library handles it:
boost.org/doc/libs/1_40_0/libs/serialization/doc/serialization.html
Are you doing this in some kind of tight loop where you need the efficiency of a good map? If so, then member function pointers (as you linked to above) is a good way to go. (At least it is after you work around the problem #Tim mentioned of keeping member function pointers to different types in the same collection ... let the language abuse begin!)
On the other hand, if this is in code that's user-driven, it might be more legible to just be totally uncool and write:
if( funcName=="A.b" )
{
A a;
a.b();
} else
// etc etc etc
For the higher-performace case, you can supplement the same approach with a parse step and some integer constants (or an enum) and use a switch. Depending on your compiler, you might actually end up with better performance than using member function pointers in a map:
switch( parse(funcName) )
{
case A_b:
{
A a;
a.b();
}
break;
}
(Of course this breaks down if you want to populate your list of possibilities from different places ... for example if each class is going to register itself during startup. But if you have that kind of object infrastructure then you should be using interfaces instead of pointers in the first place!)