patterncppMinor
Fluent interface and polymorphism for building a scene with shapes
Viewed 0 times
withpolymorphismbuildinginterfaceshapesforandfluentscene
Problem
I would like to improve the interfaces of some polymorphic classes going from positional to named parameters and I came up with the fluent interface.
The following is the most clean, compact and compilable (-std=c++11 required) example that I have been able to come up with:
I have a couple of issues with this:
How would you address these issues and improve the code? C++1y is allowed and preferred to Boost?
For further improvements see the related question: Variadic templates and pointers to member functions to achieve a named-parameters interface in C++
The following is the most clean, compact and compilable (-std=c++11 required) example that I have been able to come up with:
#include
#include
#include
#include
using namespace std;
struct Figure {
string _name;
Figure * name(const string & str) { _name=str; return this; }
virtual double area() const=0;
};
struct Circle: Figure {
double _radius;
Circle * radius(double r) { _radius=r; return this;}
double area() const override {return M_PI*_radius*_radius;}
};
struct Square: Figure {
double _side;
Square * side(double s) { _side=s; return this;}
double area() const override {return _side*_side;}
};
struct Scene {
vector v;
~Scene() { for (auto & f : v) delete f; }
Scene & add(Figure * f) {v.push_back(f); return *this;}
double total_area() const {
double total=0;
for (auto f : v) total += f->area();
return total;
}
};
int main() {
Scene scene;
scene.add((new Circle)->radius(1.)->name("c1"))
.add((new Square)-> side(1.)->name("s1"));
cout << "Total area: " << scene.total_area() << endl;
return 0;
}I have a couple of issues with this:
- That is an ugly place to have a
newoperator, could it be avoided somehow?
- After having called the method
name("name")the type is lost so there is still an ordering to respect:add((new Square)->name("s1")->side(1.))will not compile. You should imagine to have many levels of inheritance and lots of parameters to be setted!
How would you address these issues and improve the code? C++1y is allowed and preferred to Boost?
For further improvements see the related question: Variadic templates and pointers to member functions to achieve a named-parameters interface in C++
Solution
Another thing to consider in your current design:
You are calling the destructor of the base here, not the derived classes' destructors. Remember to make a virtual destructor in your class to solve this problem.
~Scene() { for (auto & f : v) delete f; }You are calling the destructor of the base here, not the derived classes' destructors. Remember to make a virtual destructor in your class to solve this problem.
Code Snippets
~Scene() { for (auto & f : v) delete f; }Context
StackExchange Code Review Q#42647, answer score: 9
Revisions (0)
No revisions yet.