Free interfaces and inheritance in C ++

I would like to create a base (abstract) class (let it be called type::base ) with some common functionality and a free interface, the problem I came across is the return type of all these methods

  class base { public: base(); virtual ~base(); base& with_foo(); base& with_bar(); protected: // whatever... }; 

Now I can make subtypes, for example:

  class my_type : public base { public: myType(); // more methods... }; 

The problem arises when using subtypes such as this:

  my_type build_my_type() { return my_type().with_foo().with_bar(); } 

This does not compile because we are returning the base instead of my_type.

I know that I can simply:

  my_type build_my_type() { my_type ret; ret.with_foo().with_bar(); return ret; } 

But I thought, how can I implement it, and I did not find any valid ideas, suggestions?

+7
c ++ inheritance fluent-interface
source share
5 answers

This "type loss" problem can be solved with patterns - but it is rather complicated.

Eg.

 class Pizza { string topping; public: virtual double price() const; }; template <class T, class Base> class FluentPizza : public Base { T* withAnchovies() { ... some implementation ... }; }; class RectPizza : public FluentPizza<RectPizza, Pizza> { double price() const { return length*width; :) } }; class SquarePizza : public FluentPizza<SquarePizza, RectPizza> { ... something else ... }; 

Then you can write

 SquarePizza* p=(new SquarePizza)->withAnchovies(); 

The pattern is that instead of

 class T : public B 

you write

 class T : public Fluent<T, B> 

Another approach might not be to use a free interface for objects, but instead of pointers:

 class Pizza { ... }; class RectPizza { ... }; class SquarePizza { ... whatever you might imagine ... }; template <class T> class FluentPizzaPtr { T* pizza; public: FluentPizzaPtr withAnchovies() { pizza->addAnchovies(); // a nonfluent method return *this; } }; 

Use this:

 FluentPizzaPtr<SquarePizza> squarePizzaFactory() { ... } FluentPizzaPtr<SquarePizza> myPizza=squarePizzaFactory().withAnchovies(); 
+4
source share

You must return references / pointers, and you do not need to store type information.

 class base { public: base(); virtual ~base(); base &with_foo(); base &with_bar(); protected: // whatever... }; class my_type : public base { public: my_type(); // more methods... }; base *build_my_type() { return &new my_type()->with_foo().with_bar(); } 

You already have a virtual destructor. Presumably you have other virtual functions. Access everything through the base type and the virtual functions declared there.

+5
source share

One solution will work as follows:

 return *static_cast<my_type*>(&my_type().with_foo().with_bar()); 

Using static_cast basically tells the compiler "I know what I'm doing here."

0
source share

In C ++, you should keep pointers or references, not values. In addition, you can explain what you mean by “free interfaces”.

-one
source share

The way I do this in C #, and I believe that this works in C ++, is also to provide a default implementation for with_foo() and with_bar() ... Excuse my C #, but:

 class base { virtual base with_foo() { throw new NotImplementedException(); } virtual base with_bar(); { throw new NotImplementedException(); } } 
-2
source share

All Articles