Common solution for initializing const member variable in abstract base class - c++

Given the following situation
class Base
{
public:
Base(double par1, double par2)
:
par1_(par1),
par2_(par2)
{}
const double value_;
protected:
const double par1_, par2_;
virtual double Calc_Value() = 0;
};
class Derived_A : public Base
{
public:
Derived_A(double par1, double par2)
:
Base(par1, par2)
{}
protected:
double Calc_Value()
{
// <code to calc value with par1_ and par2_>
}
};
class Derived_B : public Base
{
public:
Derived_B(double par1, double par2, double par3)
:
Base(par1, par2),
par3_(par3)
{}
const double par3_;
protected:
double Calc_Value()
{
// <code to calc value with par1_, par2_ and par3_>
}
};
int main()
{
std::vector<Base*> my_vector;
// do stuff using polymorphism
}
This has been bugging me for some time. I would like to initialize value_ with Calc_Value() when creating an object of Derived_A or Derived_B. I know that only Base
can initialize its const members. Now, my class objects are mostly some sort of containers which calculate the necessary values when they are created. So they should be read only.
I know I could make value_ not const, but that would make it mutable. Most solutions I found in the internet is just to create an additional constructor in Base but then I would have to declare par3_ in the base class which means, every time there is a derived_A object it will have a par3_ member variable without ever using it. Also, imagine I want to have more Derived classes with different Calc_Value() functions, do I then need to declare a constructor for every additional subclass? So far, I have overcome this problem with just making the Calc_Value() function public and therefore there was no need for a public const member variable. But when accessing the object via a function, the round brackets reduce readability in my opinion, which is why I would like to have a const member variable in Base.
Is there a common solution to this problem?

You could have a const double& in your base class and store the double in your derived class. Something like this.
#include <iostream>
struct Foo {
Foo(const double& ref) : value(ref) {}
const double& value;
};
struct Bar : Foo {
Bar(const double p1, const double p2) : Foo (value), value(p1 + p2) {}
private:
double value;
};
int main() {
Bar b(5, 3);
Foo* f = &b;
std::cout << f->value;
}
Here Bar is allowed to modify value, but since Base has a const ref you can't modify the value using the reference.
If you need Bar::value to be const as well, you would need to initialize it in the constructor initializer list. If you additionally require a function to calculate that value it can't be a member function, since you can't call a member function before the object has been constructed.
In that case you could make Calc_value a static member function and pass it the parameters it needs from the constructor of Bar
struct Bar : Foo {
Bar(const double p1, const double p2) : Foo (value), value(Calc_value(p1, p2)) {}
private:
static double Calc_value(const double p1, const double p2) {
return p1 + p2;
}
double value;
};
It just seems like you are making you code a bit overly complicated just to avoid writing () at this point.

Related

Using template metaprogramming to provide strongly-typed coordinate systems

I'm attempting to define a 3d 'Coordinate' class that is strongly-typed on a 'CoordinateSystem' parameter. Simplified version of the current mechanism I'm using:
class CoordinateBase {
protected:
double a, b, c;
/* millions of constructors */
}
class System1 : protected CoordinateBase {
public:
double& X() {return a;}
double& Y() {return b;}
double& Z() {return c;}
protected:
/* millions of constructors */
}
class System2 : protected CoordinateBase {
public:
double& Lat() {return a;}
double& Lon() {return b;}
double& Alt() {return c;}
protected:
/* millions of constructors */
}
template<typename T>
class Coordinate : public T {
public:
/* millions of constructors */
}
This works, but I'm not happy with the amount of boilerplate involved at each level in the tree (no-argument/explicit values/copy/move constructors, assignment operators). I would like to preserve the ability to have different names for the coordinate axes for different systems.
Using something like the CRTP seems helpful; then I could have the members that store the actual coordinate values in the Coordinate class and use static polymorphism to get at them from System1 and System2. Unfortunately, I can't do this:
template<typename T>
class Coordinate : public T<Coordinate<T>>
Or, at least, the compiler won't let, possibly because I'm missing some syntax.
Another possibility I considered was putting all the enable/disable logic in Coordinate:
template<typename T>
class Coordinate {
public:
std::enable_if<std::is_same<T, System1>::value, double&> X() {return a;}
private:
double a;
}
But that's going to get rather ugly rather fast and puts all the unpleasant template machinery where innocent users of this class will see it.
I'm not sure what the best approach to this sort of thing are. How can I avoid having to define so many boilerplate constructors/assignment operators while keeping the interface I'd like?
template<typename T>
class Coordinate : public T<Coordinate<T>>
The code above is not valid C++ because T is a type, but you're using is as if it was a template. This is also not CRTP - here's an example of proper CRTP:
template <typename T>
struct base
{
auto& as_derived() { return static_cast<T&>(*this); }
const auto& as_derived() const { return static_cast<const T&>(*this); }
};
struct derived : base<derived>
{
// ...
};
You could try using CTRP in this way:
template <typename T>
struct base
{
auto& as_derived() { return static_cast<T&>(*this); }
const auto& as_derived() const { return static_cast<const T&>(*this); }
double _x, _y, _z;
base(double x, double y, double z) : _x{x}, _y{y}, _z{z} { }
base(double v) : _x{v}, _y{v}, _z{v} { }
};
struct coord : private base<coord>
{
public:
using base<coord>::base;
auto& x() { return this->_x; }
auto& y() { return this->_y; }
auto& z() { return this->_z; }
};
struct geocoord : private base<geocoord>
{
public:
using base<geocoord>::base;
auto& lat() { return this->_x; }
auto& lon() { return this->_y; }
auto& alt() { return this->_z; }
};
int main()
{
coord c0{1,2,3};
geocoord c1{1};
c0.x() = 10;
c1.alt() = 22;
}
live example on wandbox
Ended up solving the problem like this:
template<typename T>
class CoordinateBase {
protected:
Coordinate<T>* upcast() {return static_cast<Coordinate<T>*>(this);}
const Coordinate<T>* upcast() const {return static_cast<const Coordinate<T>*>(this);}
};
class System1 : private CoordinateBase<System1> {
double& X() {return upcast()->c1;}
// other coordinates etc.
};
template<typename T>
class Coordinate : public T {
public:
/* Constructors */
private:
double c1;
double c2;
double c3;
friend class System1;
};
typedef Coordinate<System1> System1Coordinate;
So sorta-CRTP but I'm relying on convention to make the static_cast<> safe instead of a template parameter and convention. I've elided some namespaces and things that mean CoordinateBase and System1 aren't very exposed to the public.
The advantages of this approach:
Coordinate system classes just have the operations that coordinate system specifically allows (mostly getting the coordinates)
All the constructors live at the top layer, so no need to define or using them in lower down
There's a single class at the top of the hierarchy where I can define things for all coordinates (or some significant subset), like arithmetic operations
Relatively safe. I can static_assert that Coordinate has been passed something deriving from CoordinateBase, I can keep all the systems in their own namespace with a name like 'Internal' so people aren't encouraged to use them, coordinate systems can be made abstract so that they can't be instantiated on their own, if you forget to add the 'friend' declaration it won't compile, and you can only access the coordinates via the appropriate coordinate names.
Easy to understand.
Disadvantages:
No real way to ensure that the static_cast in CoordinateBase is safe, other than convention.
Friend declarations

C++ static member modifiers for subclasses

Consider the following code:
#include <stdio.h>
#include <iostream>
/// Header-file
class Base {
public:
virtual void do_something() const =0;
int GetAttrib () const {return constattribute_;};
static const int constattribute_;
};
typedef Base* Derived_Ptr; //<< adress derived classes by their base-class ptr; so no templates for Base
class DerivedA : public Base {
// static const int constattribute_; //<< change this static attribute for all DerivedA class instances and their derivatives
void do_something() const {};
};
class DerivedB : public Base {
// static const int constattribute_; //<< change this static attribute for all DerivedB class instances and their derivatives
void do_something() const {};
};
/// CC-file
using namespace std;
const int Base::constattribute_(0);
const int DerivedA::constattribute_(1); //<<error: no such variable 'constattribute' in class DerivedA
const int DerivedB::constattribute_(2); //<<error: no such variable 'constattribute' in class DerivedB
int main(void) {
Derived_Ptr derivedA = new DerivedA();
Derived_Ptr derivedB = new DerivedB();
cout << derivedA->GetAttrib() << derivedB->GetAttrib() <<endl;
return 0;
};
The intend being that i have some abstract interface (Base) which defines also a variable, which should be present for all derived classes, and is retrievable. All flavours of subclasses should be forced to/able to redefine their specific value for this variable, at best during class declaration (the values are known at the time the class is declared after all).
I want to achieve code, not altering the main()-program so that the output is '12' and not as of now (uncommenting current lines in the code) '00' (Doing so shadows the fields from base class).
I tried to look into the matter, and there are different paths for solutions, many of which however go contrary to my intuition:
1. Some follow the CRTP pattern, which is however impossible if I want to address my subclasses by their base-ptr in main.
2. Other solutions require to virtualize the 'GetAttrib()' function for every derived instance., which is cumbersome, and action of modifying the attribute is masked within a function definition.
3. A third possibility is to remove the static pattern and have the 'constattribute_' field as a regular member, which however forces me to drag it through all constructors as a parameter.
I am quite sure that there must be some smarter way to do this. Any hints are appreciated.
Using CRTP may get you what you want, assuming you don't have to access GetAttr() through Base* and can leave without constattribute_ in Base itself. Just follow the rule that every programming problem can be solved by entering another level of indirection, which I did below:
class Base {
public:
virtual void do_something() const = 0;
virtual ~Base() // should define it as you are using Base*
{
}
};
typedef Base* Derived_Ptr;
template<class T>
class BaseConstAttr : public Base
{
public:
int GetAttrib () const
{
return(constattribute_);
};
static const int constattribute_;
};
class DerivedA : public BaseConstAttr<DerivedA>
{
public:
void do_something() const
{
};
};
class DerivedB : public BaseConstAttr<DerivedB>
{
public:
void do_something() const
{
};
};
template<> const int BaseConstAttr<DerivedA>::constattribute_(1);
template<> const int BaseConstAttr<DerivedB>::constattribute_(2);
If you need GettAttr from top to bottom of the inheritance tree you can modify the above code a bit, but this will cost you making GetAttr virtual (but still one implementation only):
class Base {
public:
virtual void do_something() const = 0;
virtual int GetAttrib () const = 0;
virtual ~Base() // should define it as you are using Base*
{
}
};
typedef Base* Derived_Ptr;
template<class T>
class BaseConstAttr : public Base
{
public:
int GetAttrib () const
{
return(constattribute_);
};
static const int constattribute_;
};
class DerivedA : public BaseConstAttr<DerivedA>
{
public:
void do_something() const
{
};
};
class DerivedB : public BaseConstAttr<DerivedB>
{
public:
void do_something() const
{
};
};
template<> const int BaseConstAttr<DerivedA>::constattribute_(1);
template<> const int BaseConstAttr<DerivedB>::constattribute_(2);
Please note that I don't know how well (or bad) it will behave with deep inheritance tree (ie. when inheriting from DerivedA and/or DerivedB). In this case I would probably remove BaseConstAttr from inheritance tree right below Base and would try to inject it between most derived class and its predecessor or use multiple inheritance.
What you are requesting requires virtual dispatch somewhere, because you don't know the type of the object you are dealing with until runtime. The purpose of virtual dispatch is to solve exactly the problem you are facing.
The simplest solution is what you have given as number 2: make GetAttrib() virtual, and implement it on each derived class where you introduce a shadowing constattribute_.
static variable in base class is single instance hence it will be reflected same in derived class.
You can make same static member variable in derived class with specific different value you want. Now make getter member function of static variable in Base class as virtual and overload it in derived class which returns is static instance value.
I have update your code to work it, please check ..
#include <iostream>
using namespace std;
class Base {
public:
static const int constattribute_;
virtual void do_something() const =0;
virtual int GetAttrib () const {return constattribute_;};
};
typedef Base* Derived_Ptr; //<< adress derived classes by their base-class ptr; so no templates for Base
class DerivedA : public Base {
static const int constattribute_; //<< change this static attribute for all DerivedA class instances and their derivatives
void do_something() const {};
int GetAttrib () const {return constattribute_;};
};
class DerivedB : public Base {
static const int constattribute_; //<< change this static attribute for all DerivedB class instances and their derivatives
void do_something() const {};
int GetAttrib () const {return constattribute_;};
};
const int Base::constattribute_(0);
const int DerivedA::constattribute_(1); //<<error: no such variable 'constattribute' in class DerivedA
const int DerivedB::constattribute_(2); //<<error: no such variable 'constattribute' in class DerivedB
int main(void) {
Derived_Ptr derivedA = new DerivedA();
Derived_Ptr derivedB = new DerivedB();
cout << derivedA->GetAttrib() << derivedB->GetAttrib() <<endl;
return 0;
};
You should get desired output.
Note : Remember all member variables and func in derived class are private.

Attempting to reference a deleted function in objects factory

I get next error, when compining code.
Error C2280 'Square::Square(void)': attempting to reference a deleted function objectfactory.h 11
I have next object factory, for objects:
template<class ID, class Base, class ... Args> class GenericObjectFactory {
private:
typedef Base* (*fInstantiator)(Args ...);
template<class Derived> static Base* instantiator(Args ... args) {
return new Derived(args ...);
}
std::map<ID, fInstantiator> classes;
public:
GenericObjectFactory() {}
template<class Derived> void add(ID id) {
classes[id] = &instantiator<Derived>;
}
fInstantiator get(ID id) {
return classes[id];
}
};
Base class for example:
class BaseFigure
{
private:
BaseFigure(const BaseFigure&);
int m_params_num;
public:
BaseFigure() : m_params_num(0) {};
virtual void draw(WDraw &drawer)=0;
virtual void boundingBox(WDraw &drawer) = 0;
virtual ~BaseFigure() {};
};
And derived class from BaseFigure:
class Square :
public BaseFigure
{
private:
Point2d points[2];
public:
std::string type();
void draw(WDraw &drawer);
void boundingBox(WDraw &drawer);
~Square();
};
Square realization below:
void Square::draw(WDraw &drawer) {
Point2d cournerSecond(points[0].x(), points[1].y()), cournerFour(points[1].x(), points[0].y());
drawer.drawSegment(points[0], cournerSecond);
drawer.drawSegment(cournerSecond, points[1]);
drawer.drawSegment(points[1], cournerFour);
drawer.drawSegment(cournerFour, points[0]);
}
void Square::boundingBox(WDraw &drawer) {
this->boundingBox(drawer);
}
Example of using:
GenericObjectFactory<std::string , BaseFigure> figureFactory;
figureFactory.add<Square>("sq");
BaseFigure *sq = figureFactory.get("sq")();
I can't understand, where is error?
P.S Added Point2D and WDraw. All methods of this classes have realization.
class Point2d
{
public:
Point2d(double xx, double yy);
virtual ~Point2d(void);
double x() const { return m_dX; }
double y() const { return m_dY; }
private:
double m_dX;
double m_dY;
};
class WDraw
{
public:
WDraw(void);
virtual ~WDraw(void);
virtual void drawSegment(const Point2d& p1, const Point2d& p2);
};
This line:
classes[id] = &instantiator<Derived>;
sets up your instantiator to use this instantiated function:
static BaseFigure* instantiator() {
return new Square();
}
But Square isn't default-constructible, because its member:
Point2d points[2];
isn't default-constructible, because it has a user-declared non-default constructor:
Point2d(double xx, double yy);
hence the error. The implicitly declared Point2d default constructor is declared as deleted, which makes the implicitly declared default constructor of Square declared as deleted as well.
To make this work, you'd have to either add a default constructor to Point2d or allow a way to pass in arguments through Square's constructor into points. Probably the latter makes the most sense.
Barry already answered with the root cause. For the records, here a solution using your very nice variable argument template for a generic constructor:
Modified example of use:
GenericObjectFactory<std::string, BaseFigure, Point2d, double> figureFactory; //<===== A square could be constructed with top left point + width
figureFactory.add<Square>("sq");
BaseFigure *sq = figureFactory.get("sq")(Point2d(1.0,2.0), 2.0); //<===== Instatiate with right arguments
The error message then clearly shows that the appropriate constructor isn't found. Let's add it:
Square(Point2d tl, double w)
{
points[0] = tl;
points[1] = Point2d(tl.x()+w, tl.y()+w);
}
The array can't unfortunately not be initialized in the mem-initializer, so Point2d needs also a default constructor. So add it, and it compiles fine !

Object Factory with different parameters

I've been looking at factory method and struggled to find a solution to my problem (although i have the feeling it is straight forward.I'm trying to create objects that come from the same derived class, which is know in advance but they have different parameters.
class Base
{
public:
Base(){};
~Base(){};
std::string name;
double base_input;
double output;
virtual void relation_function()=0;
};
class Derived1 : public Base
{
public:
double private_input;
int multiplier;
Derived1(std::string , double , double , int);
~Derived1(){};
virtual void relation_function();
};
class Derived2 : public Base
{
public:
double private_input;
int multiplier;
Derived2(std::string , double , int);
~Derived2(){};
virtual void relation_function();
};
the parameters are injected in the derived class based on their constructors.
Derived1::Derived1(std::string input_name, double input_base_input,double input_private_input,
int input_multiplier){
name=input_name;
base_input=input_base_input;
private_input=input_private_input;
multiplier=input_multiplier;
};
Derived2::Derived2(std::string input_name,double input_private_input,int input_multiplier)
{
name=input_name;
private_input=input_private_input;
multiplier=input_multiplier;
void relation_function();};
void Derived2:: relation_function(){output=multiplier*private_input;};
void Derived1:: relation_function(){output=multiplier*base_input*private_input;};
Currently i'm creating instance of the derived class manually as follows
std::vector<std::string> v(3);
v[0]="a";v[1]="b";v[2]="c";
for (int n=0;n<=2;n++)
Base* pderived1(new Derived1(v[n],2,2,1));
std::vector<std::string> v(2);
v[0]="d";v[1]="e";
for (int n=0;n<=1;n++)
Base* pderived1(new Derived1(v[n],5,9,9));
which is not ideal, i need to create first a pointer to the constructor of the derived class to "fix"/"freeze" some of the paramters in the constructor functions before a number of instances are created from each derived class.
base* (*pconstructor){string, double, double, int) = Derived (string, 2,2,1)
the aim is to use this pointer to the constructor as the main tool to dicate the paramaters before passing to the following functions to create the object. the function below would act as a factory to create the number of instances/objects required from derived1 or derived which may have different parameters in their constructor functions like derived2.
base* function(std::vector<string>){ create instances.. }
i dont know how to create the pointer to manipulate the constructor parameters nor the function that would be used to create the instances.. Any clues, please..
Thanks you all in advance for your help from a c++ novice!
From the question, it's unclear that what's the actual goal. However, I am not aware if you can have a pointer to member function for constructor / destructor. So you have to give up for that option.
It's better to do whatever check while constructor instance itself. Also following is a bad bad idea, as it leaks memory:
for (int n=0;n<=1;n++)
Base* pderived1(new Derived1(v[n],5,9,9));
You are overwriting pderived1 more than once. Cautious with use of new/malloc.
good solution to this problem is just providing functions with different parameters:
#include <string>
#include <typeinfo>
#include <vector>
class FactoryFunction;
class Factory {
public:
template<class T, class P1, class P2>
void reg2(T (*fptr)(P1, P2));
template<class T, class P1, class P2, class P3>
void reg3(T (*fptr)(P1,P2,P3));
template<class T, class P1, class P2, class P3, class P4>
void reg4(T (*fptr)(P1,P2,P3,P4));
private:
std::vector<FactoryFunction*> vec;
};
Base *derived1_factory(std::string s, double d1, double d2, int i)
{
return new Derived1(s,d1,d2,i);
}
int main() {
Factory f;
f.reg4(&derived1_factory);
}
Edit: This design also requires some stuff that might be difficult to figure out, in particular the following classes:
class FactoryFunction {
public:
virtual int NumParams() const=0;
virtual void set_parameter(int i, void *p)=0;
virtual std::string parameter_type(int i) const=0;
virtual void *return_value() const=0;
virtual std::string return_type() const=0;
};
template<class T, class P1>
class FactoryFunction1 : public FactoryFunction
{
public:
FactoryFunction1(T (*fptr)(P1)) : fptr(fptr) { }
int NumParams() const { return 1; }
void set_parameter(int i, void *p) { switch(i) { case 0: param1 =*(P1*)p; break; }; }
std::string parameter_type(int i) const { switch(i) { case 0: return typeid(P1).name(); }; }
void *return_value(int i) const { return_val = fptr(param1); return (void*)&return_val; }
std::string return_type() const { return typeid(T).name(); }
private:
T (*fptr)(P1);
T return_val;
P1 param1;
};
Then a function like reg1 could be implemented to store new FactoryFunction1<T,P1>(fptr) to a std::vector<FactoryFunction*>.
Obviously reg1/reg2/reg3 functions can have std::string as a parameter too.
Edit: oh, reg4 is just missing implementation (you need to implement other functinons too).
template<class T, class P1, class P2, class P3, class P4>
void Factory::reg4(T (*fptr)(P1,P2,P3,P4))
{
vec.push_back(new FactoryFunction4(fptr));
}
Lets hope it compiles now :)

Override number of parameters of pure virtual functions

I have implemented the following interface:
template <typename T>
class Variable
{
public:
Variable (T v) : m_value (v) {}
virtual void Callback () = 0;
private:
T m_value;
};
A proper derived class would be defined like this:
class Derived : public Variable<int>
{
public:
Derived (int v) : Variable<int> (v) {}
void Callback () {}
};
However, I would like to derive classes where Callback accepts different parameters (eg: void Callback (int a, int b)).
Is there a way to do it?
This is a problem I ran in a number of times.
This is impossible, and for good reasons, but there are ways to achieve essentially the same thing. Personally, I now use:
struct Base
{
virtual void execute() = 0;
virtual ~Base {}
};
class Derived: public Base
{
public:
Derived(int a, int b): mA(a), mB(b), mR(0) {}
int getResult() const { return mR; }
virtual void execute() { mR = mA + mB; }
private:
int mA, mB, mR;
};
In action:
int main(int argc, char* argv[])
{
std::unique_ptr<Base> derived(new Derived(1,2));
derived->execute();
return 0;
} // main
Even if such a thing were possible, it no longer makes much sense to have it as a virtual function, as the derived instantiations couldn't be called polymorphically via a pointer to the base class.
don't think this will be possible, because you can never interface it back to Variable.
This is what i mean
int a=0; int b = 0;
Variable<int>* derived = new Derived();
derived->Callback(a, b); //this won't compile because Variable<int> does not have Callback with 2 vars.
I know this there is an accepted answer, but there is one (ugly) way to achieve what you want, although I would not recommend it:
template <typename T>
class Variable
{
public:
Variable (T v) : m_value (v) {}
virtual void Callback (const char *values, ...) = 0;
private:
T m_value;
};
class Derived : public Variable<int>
{
public:
Derived (int v) : Variable<int> (v) {}
virtual void Callback (const char *values, ...) {
}
};
Now, you can use:
int a=0;
double b = 0;
Variable<int>* derived = new Derived(3);
derived->Callback("");
derived->Callback("df", a, b);
You need the values argument in order to obtain the remaining arguments inside the method. You also need to know the argument types, and pass them like printf does.
This method is error prone, as you must match the argument types on values with the real argument types.
You will have to add an overload of Callback in the base class that accepts these parameters. It would also be possible to do bad things, like accept a void*, or pass in a raw pointer-to-bytes.
The only scenario in which it is valid to alter virtual function signature is when you override the return value to something polymorphic to the original return value, e.g. *this.