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 !
Related
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.
I need to build a C++ program the does function composition of 2 objects.
The objects can be either a polynome, a rational function or a composed function.
I have an abstract class named 'func'. I also have 2 classes that inherited 'func', named 'ratfunc'and 'polynom'.
A third class 'compfunc', also inherits 'func' and it's constructor header is given to me.
Comfunc receives 2 abstract objects from the 'func' class (by reference) and needs to compose a new function out of them (syntax: new compfunc(*outer,*inner). outer,inner are *func)
Outter and inner can be either ratfunc, polynome, or comfunc itself.
My question is how can I build a constructor like this WITHOUT using templates and without knowing the objects classes.
EDIT:
The code:
Main:
func* outer;
func* inner;
char* outer_name = strtok(func_value, ",");
char* inner_name = strtok(NULL, ",");
try{
outer = func_list.at(outer_name);
inner = func_list.at(inner_name);
func_list[string(outer_name)+"("+string(inner_name)+")"]=new
compfunc(*outer,*inner);
}
Func class (Abstract):
class func {
public:
func(); //constructor
func(const func& f); //copy constructor
virtual ~func();
protected:
bool flag; //values has been assigned, initialised to false in the constructor
};
Polynom class:
class polynom : public func {
public:
polynom(); //default constructor
polynom(int n, int* coefs); //constructor
polynom(const polynom& pol); //copy constructor
~polynom(); //destrcutor
protected:
int n_; //order of the polynom
int* coefs_; //coefficients
};
Ratfunc class:
class ratfunc : public func{
public:
ratfunc(const polynom& p, const polynom& q); //constructor
ratfunc(const ratfunc& rf); //copy constructor
~ratfunc(); //desctrcutor
protected:
polynom p_; //down
polynom q_; //up
};
Compfunc:
class compfunc : public func{
public:
compfunc(const func& outter, const func& inner);
compfunc(const compfunc& cf); //copy constructor
~compfunc(); //destrcutor
protected:
func* outer_;
func* inner_;
};
Thanks!!
Because you are passing the classes by const reference, I assume you want to copy them. For that you will need additional virtual member function clone which will return a pointer to a dynamically allocated copy of the object.
class func {
...
virtual func* clone() const;
...
};
class polynom: public func {
...
virtual polynom* clone() const override {
return new polynom(n_, coefs_);
}
...
};
class compfunc: public func {
...
compfunc(const func& outter, const func& inner): outer_(outter.clone()), inner_(inner.clone()) {}
...
virtual compfunc* clone() const override {
...
}
};
This way you can copy the passed objects regardless of their dynamic type.
I am trying to design a C++ Template class which will contain all the features of a Tree(i.e. appendChild, childCount). I want to then extend from this template class and design custom Tree class with existing features (read as Methods) as well as extra features.
So far I got this.
#include <iostream>
#include <list>
/* TREE TEMPLATE CLASS */
template <class T>
class TreeTemplate
{
public:
TreeTemplate();
void appendChild(T*);
int getChildCount();
protected:
std::list<T*> m_childList;
};
/* Constuctor */
template <class T>
TreeTemplate<T>::TreeTemplate(){}
template <class T>
void TreeTemplate<T>::appendChild(T* t)
{
m_childList.push_back(t);
}
template <class T>
int TreeTemplate<T>::getChildCount()
{
return m_childList.size();
}
/* CLASS INHERITTING TEMPLATE */
class TreeItem : public TreeTemplate<TreeItem>
{
public:
std::string getTestName();
TreeItem(std::string, std::string);
private:
std::string m_testID;
std::string m_testName;
};
TreeItem::TreeItem(std::string test_id, std::string test_name)
{
m_testID = test_id;
m_testName = test_name;
}
std::string TreeItem::getTestName()
{
return m_testName;
}
/* MAIN FUNCTION */
int main()
{
TreeItem *myTree = new TreeItem("9", "10");
TreeItem *child1 = new TreeItem("9.1", "10.1");
TreeItem *child2 = new TreeItem();
std::cout << myTree->getTestName() << std::endl;
myTree->appendChild(child1);
std::cout << myTree->getChildCount() << std::endl;
return 0;
}
Now, if I don't try to add some new Constructor in derived class (i.e. contructor overload), everything is good. But, if I am adding a new Constructor (as the code segment shows), I am failing to access the existing constructor (of Base Template class). I am getting following error in the line TreeItem *child2 = new TreeItem();
Am I doing something stupid here ? I can overload other methods, only failing at Constructor. How can I overload existing constructor of base template class?
There are two problems to address. The first is that when you define a constructor for a type, that type's default constructor is not implicitly generated. You can force it to be by using = default. Here is an example.
struct Foo {
Foo() = default; // Allows default construction
Foo(int value) : m_value(value) {}
int m_value;
};
The second problem is that a derived type does not inherit it's parent's class' constructors. Intuitively, in the following example, how can a constructor of type Base construct an instance of type Derived? Base is not aware of Derived's members.
class Base {
public:
Base(int x, int y) : m_x(x), m_y(y) {}
private:
int m_x;
int m_y;
};
class Derived : public Base {
public:
Derived(int x, int y, int z) : Base(x, y), m_z(z) {}
private:
int m_z;
};
void foo()
{
// If we use Base's constructor, what is m_z?
// Won't compile
Derived bar(1, 2);
}
Only the constructors of the type you are actually constructing are eligible, not it's base types' constructors. To simulate the behavior you will have to provide new constructors for the set of parameters you want to support.
class Derived : public Base {
public:
Derived(int x, int y, int z) : Base(x, y), m_z(z) {}
Derived(int x, int y) : Base(x, y), m_z(0) {}
private:
int m_z;
};
In certain cases you can work around this problem by supplying a variadic template constructor like the following example. This shouldn't be done in general, only when there is a particular need.
#include <utility>
class Base {
public:
Base(int x, int y) : m_x(x), m_y(y) {}
private:
int m_x;
int m_y;
};
class Derived : public Base {
public:
template<class ... Args>
Derived(Args&&... args) : Base(std::forward<Args>(args)...) {};
};
void foo()
{
Derived b(1, 2);
}
There are three classes.The first is a template, the second acts as generic for template and third implements the template.
template <class T>
class Shape {
T val,val_new;
public:
Shape(T initval)
{
val=initval;
}
...
};
class TwoPoint
{
int width;
int value;
public:
TwoPoint()
{
value=0;
width=0;
}
TwoPoint(int v, int w)
{
value=v;
width=w;
}
TwoPoint(const TwoPoint& t)
{
value= t.value;
width= t.width;
}
...
};
class Rectangle
{
private:
Shape<TwoPoint> val;
TwoPoint newval;
public:
Rectangle(TwoPoint i)
: val (Shape<TwoPoint> (i)) {}
....
};
I want to initialize the Rectangle and solidShape in some other class as class members and that can be done in java like:
Rectangle r = new Rectangle(new TwoPoint(0,8));
Shape<TwoPoint> solidShape = new Shape<TwoPoint>(new TwoPoint(0,5));
How can i do a similar type of thing in C++? I want to create an implementation like:
class C
{
public:
// initialize Rectangle here;
// initialize solidShape here;
}
The integer values shown here are just for illustration and can be anything.
The correct way to have a conversion constructor in C++ is through a const reference:
Rectangle(const TwoPoint& i)
This also means you can pass a temporary as parameter:
Rectangle* r = new Rectangle( TwoPoint(0,8) ); //dynamic storage
or
Rectangle r( TwoPoint(0,8) ); //automatic storage
It would also work with a pass by value, but this is the standard way of doing it.
Same goes for the Shape class:
Shape(const T& initval) //conversion constructor
and:
Shape<TwoPoint>* solidShape = new Shape<TwoPoint>( TwoPoint(0,5) ); //dynamic storage
or
Shape<TwoPoint> solidShape( TwoPoint(0,5) ); //automatic storage
In C++, new returns a pointer. But your conversion constructors take objects (not pointers to objects) by reference or value. So you need an object passed as parameter, not pointers.
If these two are class members:
if you chose to have pointers, you need to free the memory in the destructor.
if you chose automatic storage objects (what you have now), the destructors will be called when the containing object is destroyed, so you don't manually free the memory. To initialize automatic storage objects that are class members, you need to use an initialization list:
Like this:
class C
{
Shape<TwoPoint> solidShape;
Rectangle r;
public:
C() : solidShape(TwoPoint(0,5)), r( TwoPoint(0,8) ) {} //initialization list in constructor
};
We use const references as constructor parameters and initialization constructor chain:
template <class T>
class Shape {
T val,val_new;
public:
Shape(const T & initval) :
val(initval)
{
}
...
};
class TwoPoint
{
int width;
int value;
public:
TwoPoint() :
value(0),
width(0)
{
}
TwoPoint(int v, int w) :
value(v),
width(v)
{
}
TwoPoint(const TwoPoint& t)
value(t.value),
width(t.width)
{
}
...
};
class Rectangle
{
private:
Shape<TwoPoint> val;
TwoPoint newval;
public:
Rectangle(const TwoPoint & i)
: val (Shape<TwoPoint> (i))
{}
....
};
and you create object like this:
TwoPoint t(0,8)
Rectangle r(t);
Shape<TwoPoint> shape(t);
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 :)