design problem with inheritance

J

James Kanze

[...]
Actually, I thought of a better example. I see the strategy pattern
as a way to replace behavior dynamically. There is a static version
of the strategy pattern in C++ using templates, but as far as "design
patterns" goes I see this as primarily a runtime alteration.

There are generally three alternatives: templates with a traits
class (compile time decision), the template method pattern
(runtime decision at construction time, then fixed) and the
strategy pattern (allows changing the decision on an already
constructed object). In the case of C++, there is sometimes
another reason to prefer the strategy pattern: the concrete
strategy will generally be completely constructed before the
base class constructor of the main class starts; this allows
some degree of dynamic dispatch from the base class constructor.

Also, of course, templates with traits can be used to implement
the concrete derived classes of the template method or the
strategy patterns.
 
P

Paul

Hi I see a problem with your ..
void performFly(){ bhv->fly();

bhv needs to be initialed to point to either a Fly or NoFly object. I
did a little test program with an example of initialisng a default
Constructor to NoFly and a Constructor that takes a bool value for fly
or nofly.

class FlyBehav{
public:
        virtual void Fly()=0;

};

class NoFly: public FlyBehav{
public:
        void Fly(){std::cout<<"Cannot Fly\n";}};

class CanFly: public FlyBehav{
public:
        void Fly(){std::cout<<"Flying across the sky\n";}

};

class Duck{
        FlyBehav* ptrFly;
        bool can_fly;
public:
        Duck():can_fly(0),ptrFly(new NoFly){}
        Duck(bool b):can_fly(b){
                if(b)ptrFly=new CanFly;
                else ptrFly=new NoFly;
        }
        void PerformFly(){ptrFly->Fly();}
        ~Duck(){delete ptrFly;}

};

int main() {
        Duck flying_duck(1);
        d.PerformFly();

}

HTH- Hide quoted text -

- Show quoted text -

The duck can either fly or it can't fly.

You need to design the duck as a flying duck, or a non flying duck.
THe duck cannot be impartial to flight it must know if it can fly or
not.
If you want to instantiate ducks and also derive from a basic duck
with both flying and non-flying ducks you must create two duck
classes:
flying duck and non-flyinging duck.
You cannot have a general duck that doesn't know if it can fly or not
and derived from it both flying and non-flying ducks unless you
implement the flying interfase in the derived duck type i,e: flying or
non flying.

To summarise.. basic duck cannot know about flying if you plan to
derive it into both flying and non-flying ducks. Unless it has a
generic "I don't give a ****" attitude to flying.
 
N

Noah Roberts

    [...]
Actually, I thought of a better example.  I see the strategy pattern
as a way to replace behavior dynamically.  There is a static version
of the strategy pattern in C++ using templates, but as far as "design
patterns" goes I see this as primarily a runtime alteration.

There are generally three alternatives: templates with a traits
class (compile time decision), the template method pattern
(runtime decision at construction time, then fixed) and the
strategy pattern (allows changing the decision on an already
constructed object).

When I was mentioning a "static" version of the strategy pattern I was
specifically referring to "policy based design" where one cobbles
together a larger class out of "policy" classes that are basically
strategies within some concept. For example, in Alexandrescu's book
he specifically shows how to make a Singleton policy design that
provides overloads for policies such as thread handling. One might
use a non-threading policy that doesn't do any mutex locking at all
around the singleton construction, or one might use one of a selection
of various locking strategies depending on what the program calls for.

This is closer to the strategy pattern than traits I think since
traits generally provide methods to retrieve information about a type
and rarely provide behavior alternatives themselves. Strictly
speaking though, I'm glad he called it something else.
 
J

James Kanze

[...]
Actually, I thought of a better example. I see the strategy pattern
as a way to replace behavior dynamically. There is a static version
of the strategy pattern in C++ using templates, but as far as "design
patterns" goes I see this as primarily a runtime alteration.
There are generally three alternatives: templates with a traits
class (compile time decision), the template method pattern
(runtime decision at construction time, then fixed) and the
strategy pattern (allows changing the decision on an already
constructed object).
When I was mentioning a "static" version of the strategy pattern I was
specifically referring to "policy based design" where one cobbles
together a larger class out of "policy" classes that are basically
strategies within some concept.

This is more or less what I understood. Typically, the "policy"
class(es) will be traits, but you're correct that they don't
have to be; there are many ways to customize behavior, and
traits are just the most common (at least in the circles I
frequent).

[...]
This is closer to the strategy pattern than traits I think since
traits generally provide methods to retrieve information about a type
and rarely provide behavior alternatives themselves.

Traits can provide behavior. The usual definition for a traits
class is that it is a class with no non-static functions or data
members. (I believe that this is the definition used by the
originator.) But it's really just a question of vocabulary.
Strictly
speaking though, I'm glad he called it something else.

The word "policy" is more descriptive of the use; "traits", as
defined above, is more a description of "how" (and a rather
arbitrary one at that).

Note that the idea itself is hardly new; I used it with
<generic.h>, before we had templates, and I'm sure that I didn't
invent it. Giving the pattern a name is, however, as is
formalizing it.
 
N

Noah Roberts

    [...]
Actually, I thought of a better example.  I see the strategy pattern
as a way to replace behavior dynamically.  There is a static version
of the strategy pattern in C++ using templates, but as far as "design
patterns" goes I see this as primarily a runtime alteration.
There are generally three alternatives: templates with a traits
class (compile time decision), the template method pattern
(runtime decision at construction time, then fixed) and the
strategy pattern (allows changing the decision on an already
constructed object).
When I was mentioning a "static" version of the strategy pattern I was
specifically referring to "policy based design" where one cobbles
together a larger class out of "policy" classes that are basically
strategies within some concept.

This is more or less what I understood.  Typically, the "policy"
class(es) will be traits, but you're correct that they don't
have to be; there are many ways to customize behavior, and
traits are just the most common (at least in the circles I
frequent).

No, they're not traits at all. A trait is something that provides
information about a type. Example: iterator_traits, provides category
information and other important tidbids for generic programming.

A policy isn't like this at all and usually DOES have non-static
functions. Allocators are the nearest thing I can think of in the
standard library but that's still not quite correct.

Policy host classes generally inherit from their policies.

Wiki has a rather contrived example: http://en.wikipedia.org/wiki/Policy-based_design

For a full and better description though grab a copy of Alexandrescu's
book.
 
J

James Kanze

[...]
This is more or less what I understood. Typically, the "policy"
class(es) will be traits, but you're correct that they don't
have to be; there are many ways to customize behavior, and
traits are just the most common (at least in the circles I
frequent).
No, they're not traits at all. A trait is something that provides
information about a type. Example: iterator_traits, provides category
information and other important tidbids for generic programming.

I've never heard that definition for traits before. The creator
of the concept (or at least the person who first described it,
and named it), seems to contradict himself in the definition: he
first says "it aggregates usefule types and constants", but then
says that "it provides an avenue for that 'extra level of
indirection' that solves all software problems", which suggests
more than just types and constants. (See
http://www.cantrip.org/traits.html.) And according to
Stroustrup (as quoted in
http://accu.org/index.php/journals/442), "Think of a trait as a
small object whose main purpose is to carry information used by
another object or algorithm to determine 'policy' or
'implementation details'."

In the standard, the most obvious example of a traits class is
char_traits, which is certainly a lot more than providing
information about a type: it tells std::basic_string how to do
certain operations. And the classical example of how a user
might exploit it is to make an instance of
A policy isn't like this at all and usually DOES have non-static
functions. Allocators are the nearest thing I can think of in the
standard library but that's still not quite correct.

Are you claiming that std::char_traits isn't a traits class.
Policy host classes generally inherit from their policies.

That makes for less typing when writing the class, but increases
coupling and makes the code less readable. Sounds like a poor
trade-off to me.
For a full and better description though grab a copy of
Alexandrescu's book.

Both policies and traits have been around long before
Alexandrescu wrote his book.
 
P

Paul

On Aug 29, 3:50 am, James Kanze <[email protected]> wrote:

    [...]
No, they're not traits at all.  A trait is something that provides
information about a type.  Example: iterator_traits, provides category
information and other important tidbids for generic programming.

I've never heard that definition for traits before.  The creator
of the concept (or at least the person who first described it,
and named it), seems to contradict himself in the definition: he
first says "it aggregates usefule types and constants", but then
says that "it provides an avenue for that 'extra level of
indirection' that solves all software problems", which suggests
more than just types and constants. (Seehttp://www.cantrip.org/traits.html.)  And according to
Stroustrup (as quoted inhttp://accu.org/index.php/journals/442), "Think of a trait as a
small object whose main purpose is to carry information used by
another object or algorithm to determine 'policy' or
'implementation details'."

In the standard, the most obvious example of a traits class is
char_traits, which is certainly a lot more than providing
information about a type: it tells std::basic_string how to do
certain operations.  And the classical example of how a user
might exploit it is to make an instance of
std::basic_string<char> which is case insensitive.  It's hard to
see how that differs from a policy.

Are you claiming that std::char_traits isn't a traits class.
I think the char_traits class contains both traits and policies.
Perhaps a more fitting name would be char_traits_and_policies.
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,012
Latest member
RoxanneDzm

Latest Threads

Top