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.
Related
I'm using two external libraries which define classes with identical contents (let's say Armadillo's Arma::vec and Eigen's Eigen::VectorXd). I would like to be able to convert between these classes as cleanly as possible.
If I had defined either class, it would be trivial to include a constructor or conversion operator in that class' definition, to allow me to write e.g.
Arma::vec foo(/*some constructor arguments*/);
Eigen::VectorXd bar = Eigen::VectorXd(foo);
but since both classes are from external libraries, I cannot do this. If I attemt to write a naive conversion function, e.g.
class A{
public:
int value_;
A(int value) : value_(value) {}
};
class B{
public:
int value_;
B(int value) : value_(value) {}
};
A A(const B& b){return A(b.value_);}
int main(void){
A a(1);
B b(2);
a = A(b);
}
then the function shadows the class definition, and suddenly I can't use the A class at all.
I understand that allowing A a=b to be defined would be a bad idea, but I don't see why allowing A a=A(b) would cause any problems.
My question:
Is it possible to write a function or operator to allow the syntax A a=A(b)? And if not, is there a canonical way of doing this kind of conversion?
I've seen A a=toA(b) in a few libraries, but this isn't used consistently, and I dislike the inconsistency with the usual type conversions.
Is it possible to write a function or operator to allow the syntax A a=A(b)?
No, it is not possible. The two classes involved define what conversions are possible and you can't change a class definition after it has been defined.
You will need to use a function as in your given example, although I would avoid repeating the type name and write
auto a = toA(b);
TL;DR
Best engineering practice is to use design pattern Factory by introducing function (or utility class) that consumes Eigen::VectorXd and returns Arma::vec.
Arma::vec createFrom(Eigen::VectorXd from) { ... }
Any other hacking is a waste of time and introduction of tight coupling that will strike back sooner or later. Loose coupling is essential in SW engineering.
Detailed
You might introduce descendant of the target class where you would define a constructor like you described:
class MyArma : Arma::vec {
public:
MyArma(Eigen::VectorXd from) : x(from.x), y(from.y), z(from.z) {
/* empty constructor as we are fine with initializers */
}
}
Then you'd just be able to create Arma vectors based on Eigen's vecotrs into E.g. Arma typed array
Arma::vec vecArray[] = { MyArma(eigenVect1), MyArma(eigenVect2) };
which comes from the principles of inheritance. Alternatively you could use a design pattern called Decorator where original vector (Eigen) is hidden behind the interface of the current vector (Armadillo). That involves overrding all the methods and there must be no public attribute and all the methods must have been delared as virtual... So lot of conditions.
However there are some engeneering flaws in above design. You are adding a performance overhead with Virtual Method Table, you are getting yourself in maintaining quite big and sensitive library for this purpose. And most important: You'd create technological dependency - so called spaghetti. One object shouldn't be avare about alternatives.
The documentation to armadillo gives nice hint that you should use design pattern called Factory. Factory is a standalone class or a function that combines knowledge of both implementations and contains algorihm to extract information from one and construct the other.
Based on http://arma.sourceforge.net/docs.html#imbue you'd best create a factory class that creates the target vector of the same size as the input vector and using method imbue(...) it would set the values of individual elements based on corresponding elements from the input vector.
class ArmaVecFacotry() {
Arma::vec createFrom(Eigen::VectorXd from) {
Arma::vec armaVec(from.size(), fill::none);
int currentElement = 0;
armaVec.imbue( [&]() { return from(currentElement++); } );
return armaVec;
}
}
and then simply create objects like
Eigen::VectorXd sourceVector;
Arma::vec tergetvector = std::move(ArmaVecFactory::createFrom(sourceVector));
Notes:
You can have currentElement counter outside of the lambda expression as it is captured by [&]
I am creating the vector on stack but std::move outside make sure that the memory is being used effectively without excessive copying.
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
};
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 ...; }
I have two options. Either make a class that accepts a lot arguments in its constructors, or create a lot of setter methods and an init method. I'm not sure which is preferred option, should some arguments be accepted in constructors, while others could be manually set via setter? Or am I over-thinking this?
This is a relevant question, also by me: Conflicts between member names and constructor argument names.
If after you create an object you have to call set or init to actually use it... well, that's just an awful design.
If the object is usable without some of the members initialized the way you want them to be, you can set them later on.
The golden rule here is - if you create an object, you should be able to use it without doing any other sort of initialization.
Expanding on the answer:
Say you have a shape with 10 sides, 10 corners, a color and a name, that can be connected to a different shape. The constructor should look like:
MyShape(Point c1, Point c2,...., Point c10, Color c, Name n)
As you can see, I've omitted the connected shape because it can sensibly be set to NULL if the current object is not connected. However, in the absence of any of the other parameters, the object isn't valid, so they should be set in the constructor.
A possible overload (alternitively a default argument) can be:
MyShape(Point c1, Point c2,...., Point c10, Color c, Name n,
MyShape* connectedShape /*=NULL*/)
You should provide the constructor arguments for all the members which are necessary to preserve the class invariant. In other words, object should be in valid and consistent state from the moment it is created until it is destroyed. Everything else is calling for troubles.
That being said, concessions are sometimes made, e.g. in cases of hierarchies where virtual methods are required to be called in order to provide type specific initialization. Oftentimes, this can be avoided by usage of template classes/methods (i.e. static polymorphism)
If there are class members which don't affect the class invariant, they can be set later on via setters or other methods.
the builder pattern will help here also try to coalesce the parameters to have them make sense during the setting up of the builder
As a rule of thumb, having lots of constructor parameters is a sign of a class that does too much, so try splitting it into smaller classes first.
Then try grouping some of the parameters into smaller classes or structs having their own, simpler, constructor each.
If you have sensible default values, you can use a constructor that provides parameters only for values that absolutely MUST be given when constructing a new object, and then add setters, or use static functions that copy a "starter" object, changing part of it in the process. That way, you always have consistent objects (invariants OK), and shorter constructor or function calls.
I agree with ratchet freak's suggestion of the builder pattern except that there is a trade-off in that the typical builder pattern offers no compile-time checks to insure all arguments have been included, and you can end up with an incompletely/incorrectly built object.
This was a problem enough for me that I make a compile-time checking version that might do the job for you if you can forgive the extra machinery. (There are certainly optimizations to be had as well)
#include <boost/shared_ptr.hpp>
class Thing
{
public:
Thing( int arg0, int arg1 )
{
std::cout << "Building Thing with \n";
std::cout << " arg0: " << arg0 << "\n";
std::cout << " arg1: " << arg1 << "\n";
}
template <typename CompleteArgsT>
static
Thing BuildThing( CompleteArgsT completeArgs )
{
return Thing( completeArgs.getArg0(),
completeArgs.getArg1() );
}
public:
class TheArgs
{
public:
int arg0;
int arg1;
};
class EmptyArgs
{
public:
EmptyArgs() : theArgs( new TheArgs ) {};
boost::shared_ptr<TheArgs> theArgs;
};
template <typename PartialArgsClassT>
class ArgsData : public PartialArgsClassT
{
public:
typedef ArgsData<PartialArgsClassT> OwnType;
ArgsData() {}
ArgsData( const PartialArgsClassT & parent ) : PartialArgsClassT( parent ) {}
class HasArg0 : public OwnType
{
public:
HasArg0( const OwnType & parent ) : OwnType( parent ) {}
int getArg0() { return EmptyArgs::theArgs->arg0; }
};
class HasArg1 : public OwnType
{
public:
HasArg1( const OwnType & parent ) : OwnType( parent ) {}
int getArg1() { return EmptyArgs::theArgs->arg1; }
};
ArgsData<HasArg0> arg0( int arg0 )
{
ArgsData<HasArg0> data( *this );
data.theArgs->arg0 = arg0;
return data;
}
ArgsData<HasArg1> arg1( int arg1 )
{
ArgsData<HasArg1> data( *this );
data.theArgs->arg1 = arg1;
return data;
}
};
typedef ArgsData<EmptyArgs> Args;
};
int main()
{
Thing thing = Thing::BuildThing( Thing::Args().arg0( 2 ).arg1( 5 ) );
return 0;
}
It rather depends on what you're doing. Usually it's best to set things in the constructor as these help shape how the object is used later in its lifecycle. There can also be implications of changing a value once the object has been created (e.g. a calculation factor, or file name) which might mean you have to provide functionality to reset the object - very messy.
There are sometimes arguments for providing an initialization function which is called after the constructor (when calling a pure virtual would make it difficult to initialize direct from the constructor) but you then have to keep a record of object state which adds more complexity.
If the object is a straight stateless data container then accessors and mutators might be OK but they add a lot of maintenance overhead and are rarely all used anyway.
I'd tend to stick with setting your values in the constructor and then adding accessors as and when to allow you read only access to arguments that you might need.
That depends on your architecture and tools:
If you plan to develop/prototype a large OO-hierarchy, i'd be reluctant with passing lots of information via constructors if you don't have a good IDE/editor. In this case you might end up with a lot of work each refactoring step, which might result in errors, not catched by the compiler.
If you plan to use a well integrated set of objects (e.g. through strong use of design patterns) which do not span one large hierarchy, but rather have strong iteraction, passing more data via constructors is a good thing, since changing one objects constructor does not break all the child constructors.
If the setting is required and cannot be given a default value, make it required in the constructor. That way you know it will actually be set.
If the setting is not required and can be given a default value, make a setter for it. This makes the constructor a lot simpler.
e.g. If you have a class that sends an email, the "To" field might be required in the constructor, but everything else can be set in a setter method.
My experience points me to having arguments in the constructor rather than getters and setters. If you have a lot of parameters, it suggests optional ones can be defaulted while the required/mandatory ones are the constructor parameters.
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.