named parameter idiom and inheritance

Discussion in 'C++' started by Christof Warlich, Jun 14, 2012.

  1. Hi,

    please consider the following code, using named parameters for object
    instantiation:

    class Base {
    public:
    Base(): _varBase(0) {}
    Base &varBase(int var) {_varBase = var; return *this;}
    private:
    int _varBase;
    };
    class Derived: public Base {
    public:
    Derived(): _varDerived(0) {}
    Derived &varDerived(int var) {_varDerived = var; return *this;}
    // ugly forwarding function
    Derived &varBase(int var) {varBase(var); return *this;}
    private:
    int _varDerived;
    };
    int main() {
    Derived w = Derived().varDerived(42);
    // the forwarding function is needed for all of these.
    Derived x = Derived().varBase(4711);
    Derived y = Derived().varDerived(42).varBase(4711);
    Derived z = Derived().varBase(4711).varDerived(42);
    }

    It works fine so far, but now imagine that the classes have more
    member variables and that the inheritance hierarchy is deeper than 2
    (i.e. we have classes DerivedFromDerived, ...). Then, _each_ of the
    derived classes would need a forwarding function for _every_ variable
    in _any_ of its base classes, which doesn't scale very well.

    Is anyone aware of a way to avoid these forwarding function(s)?

    Thanks for any ideas,

    Chris
     
    Christof Warlich, Jun 14, 2012
    #1
    1. Advertising

  2. On 6/14/2012 3:41 AM, Christof Warlich wrote:
    > please consider the following code, using named parameters for object
    > instantiation:
    >
    > class Base {
    > public:
    > Base(): _varBase(0) {}
    > Base&varBase(int var) {_varBase = var; return *this;}
    > private:
    > int _varBase;
    > };
    > class Derived: public Base {
    > public:
    > Derived(): _varDerived(0) {}
    > Derived&varDerived(int var) {_varDerived = var; return *this;}
    > // ugly forwarding function
    > Derived&varBase(int var) {varBase(var); return *this;}
    > private:
    > int _varDerived;
    > };
    > int main() {
    > Derived w = Derived().varDerived(42);
    > // the forwarding function is needed for all of these.
    > Derived x = Derived().varBase(4711);
    > Derived y = Derived().varDerived(42).varBase(4711);
    > Derived z = Derived().varBase(4711).varDerived(42);
    > }
    >
    > It works fine so far, but now imagine that the classes have more
    > member variables and that the inheritance hierarchy is deeper than 2
    > (i.e. we have classes DerivedFromDerived, ...). Then, _each_ of the
    > derived classes would need a forwarding function for _every_ variable
    > in _any_ of its base classes, which doesn't scale very well.
    >
    > Is anyone aware of a way to avoid these forwarding function(s)?


    I am sorry, it is unclear from what you presented here, what it is that
    you're trying to accomplish. Why would you want to expose member
    variables like that? Seems to violate any sensible encapsulation and
    implementation hiding principle.

    V
    --
    I do not respond to top-posted replies, please don't ask
     
    Victor Bazarov, Jun 14, 2012
    #2
    1. Advertising

  3. > > // ugly forwarding function
    > > Derived&varBase(int var) {varBase(var); return *this;}


    > I am sorry, it is unclear from what you presented here, what it is that
    > you're trying to accomplish.  Why would you want to expose member
    > variables like that?  Seems to violate any sensible encapsulation and
    > implementation hiding principle.


    The example just implements (part of) the "named parameter" idiom as
    described in http://www.parashift.com/c -faq-lite/ctors.html#faq-10.20
    and extends it in the presence of inheritance. I've deliberately left
    out the additional effort of proper encapsulation to concentrate on
    the issue:

    What I'd like to accomplish is to find a way to get rid of the "ugly
    forwarding function"(s) as commented in the code, as they are required
    for _every_ variable in _every_ derived class.

    Anyhow, I fear that I may be out of luck, there is most probably no
    such way :-(.

    Cheers,

    Chris
     
    Christof Warlich, Jun 14, 2012
    #3
  4. On 6/14/2012 10:34 AM, Christof Warlich wrote:
    >>> // ugly forwarding function
    >>> Derived&varBase(int var) {varBase(var); return *this;}

    >
    >> I am sorry, it is unclear from what you presented here, what it is that
    >> you're trying to accomplish. Why would you want to expose member
    >> variables like that? Seems to violate any sensible encapsulation and
    >> implementation hiding principle.

    >
    > The example just implements (part of) the "named parameter" idiom as
    > described in http://www.parashift.com/c -faq-lite/ctors.html#faq-10.20
    > and extends it in the presence of inheritance. I've deliberately left
    > out the additional effort of proper encapsulation to concentrate on
    > the issue:
    >
    > What I'd like to accomplish is to find a way to get rid of the "ugly
    > forwarding function"(s) as commented in the code, as they are required
    > for _every_ variable in _every_ derived class.


    They are required to exist in the corresponding class for _every_
    variable, yes. As many "ugly forwarding functions" as there are those
    "parameters" that you'd like to use "named", regardless of inheritance.
    Do you find that not to be true?

    > Anyhow, I fear that I may be out of luck, there is most probably no
    > such way :-(.


    Well, yeah, sort of. I speculate that you don't really want to use
    inheritance here. The article in the FAQ talks about a supplemental
    class for constructing an instance of another class, right? Why would
    there be a need to inherit that supplemental class? Perhaps it's the
    sole point of the exercise, but then it's an exercise in futility,
    really. You don't like the "forwarding functions", whereas those are
    pretty much the only reasonable way to implement the "named parameters"
    (at least as far as the FAQ is suggesting). It's like asking, 'Can I
    avoid the hardware interrupt when I perform an operation that causes a
    hardware interrupt?' The answer is "no", and there is no sense in
    looking any further.

    Of course, it's possible that I didn't understand you, in which case,
    I'm open to starting over, perhaps you could restate your problem (using
    a simpler case, but let's be close to modeling real world here).

    V
    --
    I do not respond to top-posted replies, please don't ask
     
    Victor Bazarov, Jun 14, 2012
    #4
  5. On 14.06.2012 09:41, Christof Warlich wrote:
    > Hi,
    >
    > please consider the following code, using named parameters for object
    > instantiation:
    >
    > class Base {
    > public:
    > Base(): _varBase(0) {}
    > Base&varBase(int var) {_varBase = var; return *this;}
    > private:
    > int _varBase;
    > };
    > class Derived: public Base {
    > public:
    > Derived(): _varDerived(0) {}
    > Derived&varDerived(int var) {_varDerived = var; return *this;}
    > // ugly forwarding function
    > Derived&varBase(int var) {varBase(var); return *this;}
    > private:
    > int _varDerived;
    > };
    > int main() {
    > Derived w = Derived().varDerived(42);
    > // the forwarding function is needed for all of these.
    > Derived x = Derived().varBase(4711);
    > Derived y = Derived().varDerived(42).varBase(4711);
    > Derived z = Derived().varBase(4711).varDerived(42);
    > }
    >
    > It works fine so far, but now imagine that the classes have more
    > member variables and that the inheritance hierarchy is deeper than 2
    > (i.e. we have classes DerivedFromDerived, ...). Then, _each_ of the
    > derived classes would need a forwarding function for _every_ variable
    > in _any_ of its base classes, which doesn't scale very well.
    >
    > Is anyone aware of a way to avoid these forwarding function(s)?


    http://alfps.wordpress.com/2010/05/19/cppx-how-to-do-typed-optional-arguments-in-c98/

    Cheers & hth.,

    - Alf
     
    Alf P. Steinbach, Jun 14, 2012
    #5
  6. Christof Warlich

    Luca Risolia Guest

    On 14/06/2012 09:41, Christof Warlich wrote:
    > It works fine so far, but now imagine that the classes have more
    > member variables and that the inheritance hierarchy is deeper than 2
    > (i.e. we have classes DerivedFromDerived, ...). Then, _each_ of the
    > derived classes would need a forwarding function for _every_ variable
    > in _any_ of its base classes, which doesn't scale very well.
    >
    > Is anyone aware of a way to avoid these forwarding function(s)?


    If you just want to instantiate the most derived class, use this idiom:

    template<class D>
    class Base {
    public:
    Base() : _varBase(0) { }
    D& varBase(int var) {
    _varBase = var;
    return *static_cast<D*> (this);
    }
    private:
    int _varBase;
    };

    class Derived : public Base<Derived> {
    public:
    Derived() : _varDerived(0) { }
    Derived& varDerived(int var) {
    _varDerived = var;
    return *this;
    }
    private:
    int _varDerived;
    };
     
    Luca Risolia, Jun 14, 2012
    #6
  7. Christof Warlich

    AdlerSam Guest

    AdlerSam, Jun 16, 2012
    #7
  8. Christof Warlich

    AdlerSam Guest

    > If you just want to instantiate the most derived class, use this idiom:
    >
    > template<class D>
    > class Base {
    > public:
    >      Base() : _varBase(0) { }
    >      D& varBase(int var) {
    >          _varBase = var;
    >          return *static_cast<D*> (this);
    >      }
    > private:
    >      int _varBase;
    >
    > };
    >
    > class Derived : public Base<Derived> {
    > public:
    >      Derived() : _varDerived(0) { }
    >      Derived& varDerived(int var) {
    >          _varDerived = var;
    >          return *this;
    >      }
    > private:
    >      int _varDerived;
    >
    >
    >
    >
    >
    >
    >
    > };

    Yes, that should pretty much fit my needs. Thanks a lot!
     
    AdlerSam, Jun 16, 2012
    #8
  9. AdlerSam <> writes:

    >> template<class D>
    >> class Base {
    >> public:
    >>      Base() : _varBase(0) { }
    >>      D& varBase(int var) {
    >>          _varBase = var;
    >>          return *static_cast<D*> (this);
    >>      }
    >> private:
    >>      int _varBase;
    >>
    >> };
    >>
    >> class Derived : public Base<Derived> {
    >> public:
    >>      Derived() : _varDerived(0) { }
    >>      Derived& varDerived(int var) {
    >>          _varDerived = var;
    >>          return *this;
    >>      }
    >> private:
    >>      int _varDerived;


    > Yes, that should pretty much fit my needs. Thanks a lot!


    Note that you have lost your base class, since Base<Derived1> and
    Base<Derived2> are completely unrelated. You're basically using
    templates and inheritance to factor out common text.

    -- Alain.
     
    Alain Ketterlin, Jun 17, 2012
    #9
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Steve
    Replies:
    10
    Views:
    907
    Matthias Kaeppler
    Jul 23, 2005
  2. George2

    Inheritance in Pimpl idiom

    George2, Mar 18, 2008, in forum: C Programming
    Replies:
    0
    Views:
    440
    George2
    Mar 18, 2008
  3. Fernando Cacciola

    named parameters idiom

    Fernando Cacciola, Nov 6, 2007, in forum: Ruby
    Replies:
    5
    Views:
    158
    Fernando Cacciola
    Nov 6, 2007
  4. Pacific Fox

    Named arguments and inheritance

    Pacific Fox, Nov 10, 2006, in forum: Javascript
    Replies:
    34
    Views:
    348
  5. Tuxedo
    Replies:
    2
    Views:
    579
    Tuxedo
    Feb 14, 2012
Loading...

Share This Page