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.
Related
My class has the following structure:
class S {
public:
S() {}
};
class T {
private:
std::unique_ptr<S> a;
T(S);
public:
static std::unique_ptr<T> make_item() {
std::unique_ptr<S> s_instance = std::make_unique<S>();
return std::make_unique<T>(std::move(s_instance));
}
};
However, when I try to make a unique_ptr in the make_item, it sees the constructor as private.
Is there a way to allow the use of the private constructor in a static member function of the class itself? Because one member is a unique_ptr to S (a rather heavy object), we wish not to use a copy.
As proposed by yksisarvinen in the comments, a way to solve this is to just replace make_unique<T> by std::unique_ptr<T>(new T(S)).
class S {
public:
S() {}
};
class T {
private:
std::unique_ptr<S> a;
T(S);
public:
static std::unique_ptr<T> make_item() {
// Create S
std::unique_ptr<S> s_instance = std::make_unique<S>();
return std::unique_ptr<T>(new T(s_instance));
}
};
It is possible to either declare make_unique and its internal helpers (if any) a friend function, which make the code non-portable (as said here: How to make std::make_unique a friend of my class)
Or make the constructor public but add a private element to its arguments, for example:
class S {
public:
S() {}
};
class T {
private:
struct Private
{
friend T;
private:
explicit Private() = default;
};
std::unique_ptr<S> a;
public:
T(S s, Private);
static std::unique_ptr<T> make_item() {
auto s_instance = std::make_unique<S>();
return std::make_unique<T>(std::move(s_instance), Private());
}
};
I want to enhance members of C++ classes so that assignment from/to them results in the call of a custom getter/setter.
Like
class Class
{
public:
int Member;
void SetMember(int Value); // TBD
int GetMember(); // TBD
}
and
Class Instance;
Instance.Member= 3; // Causes a call to SetMember(3);
int Data= Instance.Member; // Causes a call to GetMember();
I have found a way to force a function call upon member assignment, by turning the member type to a class holding a private value, and overloading the cast operator for reading and the assignment operator for writing.
class WrapInt
{
public:
operator int() const { return Value; }
void operator=(const int Assign) { Value= Assign; }
private:
int Value;
}
This works, but in a generic way, I cannot customize the getters/setters per member but only per data type.
Do you see a way to refine so that I can write different accessors for different members of the same type ?
Update:
I have now found a solution that satisfies my needs. The members that require a special setter are defined using a class that knows the hosting class:
template<class Parent> class WrapInt
{
public:
int operator=(const int Value) { (This->*Setter)(Value); return Value; }
operator int() { return Value; }
private:
int Value;
Parent* This;
void (Parent::*Setter)(int Value);
friend Parent;
};
Assigning such a member invokes the assignment operator, which calls a plain setter function via a pointer to method of the main class. The Get operation is implemented via the cast operator, which just returns the member value (the scheme might be enhanced to support custom getters, but I didn't need that).
This is pretty costly as every member takes an extra This pointer to the class instance and a pointer to the setter; these need to be initialized in the class constructor (if not, a crash is guaranteed).
So this takes some effort on the side of the class writer (initialization in the constructor), but then assigning to the member automatically invokes the setter, as I want.
class Class
{
public:
Class();
WrapInt<Class> Member;
private:
void SetMember(int Value); // TBD
}
Class::Class() { Member.This= this; Member.Setter= &Class::SetMember; }
On the side of the user,
Class Instance;
Instance.Member= 3; // Calls the setter SetMember
cout << Instance.Member;
that's it.
You could make your class WrapInt modifyable.
Option 1: At runtime, using a function object
class WrapInt
{
public:
operator int() const { return Value; }
void operator=(const int Assign)
{
assign_callback(Assign);
Value = Assign;
}
private:
int Value;
std::function<void (int)> assign_callback;
}
In this variant, you would have to assign the correct callbacks in the constructor of the containing class:
class Container
{
WrapInt a, b, c;
Container ()
{
a.assign_callback = ...;
b.assign_callback = ...;
c.assign_callback = ...;
}
}
Option 2: At compile-time, using inheritance
class WrapInt
{
public:
operator int() const { return Value; }
void operator=(const int Assign)
{
assign_callback(Assign);
Value = Assign;
}
private:
int Value;
virtual void assign_callback(int) = 0;
}
In this variant, you would inherit from WrapInt multiple times in the class body of the containing class
class Container
{
class WrapIntA : public WrapInt {
void assign_callback() { ... };
} a;
class WrapIntB : public WrapInt {
void assign_callback() { ... };
} b;
class WrapIntC : public WrapInt {
void assign_callback() { ... };
} c;
}
A modified version of your code:
class WrapInt
{
public:
WrapInt(std::function<int()> getter, std::function<void(int)> setter) :
getter(getter),
setter(setter)
{}
WrapInt(const WrapInt&) = delete;
WrapInt& operator =(const WrapInt&) = delete;
operator int() const { return getter(); }
void operator=(int value) { setter(value); }
private:
std::function<int()> getter;
std::function<void(int)> setter;
};
class Class
{
public:
Class() : Member([this](){ return this->GetMember();},
[this](int value) {SetMember(value); })
{}
WrapInt Member;
void SetMember(int Value); // TBD
int GetMember(); // TBD
};
Don't fight the language: C++ does not support get / set bindings to functions. You merely have to tolerate
Instance.Member() = 3;
and
int Data = Instance.Member();
Which you can provide by supplying a const function Member() that returns a const reference, and a non-const version that returns a non-const reference.
One criticism of C++ is the amount of boilerplate you need to write, especially if you need this for every member variable in your class. But really at that point, you are pretty much circumventing encapsulation entirely: you may as well make the members public unless your functions make consistency checks.
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 !
I have got this problem and don't know how to solve it.
Suppose I have these base classes:
class ValueBase
{
private:
int base_value;
public:
int GetValue();
void SetValue(int val);
virtual ValueBase* Meet(ValueBase* const a, ValueBase* const b) = 0;
}
class NodeBase
{
private:
ValueBase* base_nodeValue;
public:
bool AddValue(int val);
}
and derived class:
class Value : public ValueBase
{
public:
Value* Meet(ValueBase* a, ValueBase* b) override;
}
Is there a way to create instance of class Value in method AddValue in class NodeBase? I know that I should probably make AddValue pure virtual and implement it in derived class of NodeBase, but is there possibility to do it without this option? Can I use e.g. template method or maybe a callback to method in Value that would construct that object? Or is it just too evil to do it?
EDITED:
I don't have access to derived class Value in class NodeBase
Add a creation member function:
class ValueBase
{
public:
virtual ValueBase * create() = 0;
// ...
};
Then in NodeBase you can use base_nodeValue->create().
Derived classes implement it:
class Value : public ValueBase
{
Value * create() override { return new Value; }
};
The more common form of this pattern is a clone function, though, which does not produce a default-constructed object of the same type, but a copy:
Derived * clone() override { return new Derived(*this); }
I see no approach without changing class definitions. However, there are many approaches that involve changing class definitions, depending on what you are "allowed" to use.
A. Make AddValue() templated on the object type it should create:
class NodeBase
{
private:
ValueBase* base_nodeValue;
public:
template<class ValueType>
bool AddValue(int val) { base_nodeValue = new ValueType; }
}
...
// other code that has access to Value
node.AddValue<Value>(10);
B. Create function that creates Value (forwarding any arguments to constructor if needed) and pass it as an argument toAddValue`:
// might need to adapt syntax
class NodeBase
{
private:
ValueBase* base_nodeValue;
public:
bool AddValue(int val, ValueBase* (*creator)()) { base_nodeValue = (*creator)(); }
}
...
// other code that has access to Value
ValueBase* valueCreator() { return new Value; }
...
node.AddValue(10, valueCreator);
(May use a functor or a lambda here as well)
C. You can create a function in ValueBase that returns Value*.
class ValueBase
{
public:
static ValueBase* createValue();
};
class NodeBase
{
private:
ValueBase* base_nodeValue;
public:
bool AddValue(int val) { base_nodeValue = ValueBase::createValue(); }
};
// in a separate cpp
ValueBase* ValueBase::createValue() { return new Value; }
This is in fact similar to a factory approach: you can have createValue() accept a parameter and create different ValueBases depending on it. Having ValueBase store some pointer to creator function, you can have it not know about Value at all, just initialize that pointer at some other place, like you can register a subclass in a factory table in base class.
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 :)