Subset of derived classes accessing base class functions

Discussion in 'C++' started by fgh.vbn.rty@gmail.com, Jul 24, 2008.

  1. Guest

    Say I have a base class B and four derived classes d1, d2, d3, d4. I
    have three functions fx, fy, fz such that:
    fx should only be called by d1, d2
    fy should only be called by d2, d3
    fz should only be called by d1, d3, d4

    I think I have two options.
    (1) Make all functions virtual and define them in the required derived
    classes. This will of course lead to a lot of code duplication and
    problems in maintainability.
    (2) Keep the functions in the base class. Define some type of
    identifier (ex: a string) for each of the derived classes and add some
    checks at the top of each fx, fy, fz to ensure that only the
    appropriate di's are accessing them.

    I have implemented (2) but I'm not happy with it because I don't seem
    to use the identifier for anything else. Is it possible to use
    something like typeid instead for the same purpose?

    Is there any other alternate way to do something like this? May be a
    design pattern that can be adapted to handle such a situation?
     
    , Jul 24, 2008
    #1
    1. Advertising

  2. wrote:
    > Say I have a base class B and four derived classes d1, d2, d3, d4. I
    > have three functions fx, fy, fz such that:
    > fx should only be called by d1, d2
    > fy should only be called by d2, d3
    > fz should only be called by d1, d3, d4
    >


    > Is there any other alternate way to do something like this? May be a
    > design pattern that can be adapted to handle such a situation?


    Maybe inserting another hierarchy level an multiple hierarchy:

    class B{
    //all common thing
    virtual ~B();
    }

    class FXToImplement: public B
    {
    virtual void fx();
    virtual ~FXToImplement()=0;
    }

    class FYToImplement: public B
    {
    virtual void fy();
    virtual ~FYToImplement()=0;
    }

    class FZToImplement: public B
    {
    virtual void fz();
    virtual ~FZToImplement()=0;
    }

    class d1: public FXToImplement,FZToImplement
    {
    void fx();
    void fz();
    }

    and you can continue with the others
     
    Darío Griffo, Jul 24, 2008
    #2
    1. Advertising

  3. James Kanze Guest

    On Jul 24, 9:08 pm, wrote:
    > Say I have a base class B and four derived classes d1, d2, d3, d4. I
    > have three functions fx, fy, fz such that:
    > fx should only be called by d1, d2
    > fy should only be called by d2, d3
    > fz should only be called by d1, d3, d4


    Then you have a fundamental design problem. Something is wrong
    with this scenario. The base class doesn't know about the
    derived classes, so it can't impose any restrictions on a subset
    of them. And if the restriction comes from the derived class
    itself, then the class knows about it, and will conform to it.

    [...]
    > Is there any other alternate way to do something like this?
    > May be a design pattern that can be adapted to handle such a
    > situation?


    Perhaps you'd best describe the problem you're trying to solve,
    and not just the solution which doesn't work.

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
     
    James Kanze, Jul 24, 2008
    #3
  4. Guest

    James Kanze wrote:
    > On Jul 24, 9:08 pm, wrote:
    > > Say I have a base class B and four derived classes d1, d2, d3, d4. I
    > > have three functions fx, fy, fz such that:
    > > fx should only be called by d1, d2
    > > fy should only be called by d2, d3
    > > fz should only be called by d1, d3, d4

    >
    > Then you have a fundamental design problem. Something is wrong
    > with this scenario. The base class doesn't know about the
    > derived classes, so it can't impose any restrictions on a subset
    > of them. And if the restriction comes from the derived class
    > itself, then the class knows about it, and will conform to it.
    >
    > [...]
    > > Is there any other alternate way to do something like this?
    > > May be a design pattern that can be adapted to handle such a
    > > situation?

    >
    > Perhaps you'd best describe the problem you're trying to solve,
    > and not just the solution which doesn't work.
    >
    > --
    > James Kanze (GABI Software) email:
    > Conseils en informatique orient�e objet/
    > Beratung in objektorientierter Datenverarbeitung
    > 9 place S�mard, 78210 St.-Cyr-l'�cole, France, +33 (0)1 30 23 00 34


    Perhaps you are right :-(. Let me write out the problem in better
    terms.

    Say I have a base class called Car.
    I have four different cars Car1, Car2, Car3, Car4.
    There are three types of tyres TyreX, TyreY, TyreZ.
    TyreX can only "be applied to" Car1, Car2.
    TyreY only to Car2, Car3.
    TyreZ only to Car1, Car3, Car4.

    As the previous poster suggested I could possibly first have derived
    classes CarWithTyreX, CarWithTyreY, CarWithTyreZ. And then Car1 is
    derived from CarWithTyreX, CarWithTyreZ etc.,

    But the problem with that approach is that the Car has many other
    features (engine, windows etc.,). And I definitely shouldn't be doing
    derived classes like CarWithTyreXEngineE1..... That's why I was
    thinking of just deriving Car1, ... Car4 directly from Car and then
    applying all other functions appropriately.

    Also, note that the features aren't just "building blocks" as such.
    They can be just functions that modify the object's properties in some
    way.

    Is there a mistake in this approach?
     
    , Jul 24, 2008
    #4
  5. Hi,

    Darío Griffo schrieb:
    > class FXToImplement: public B


    probably you meant

    class FXToImplement: virtual public B

    otherwise you have multiple instances of B in your derived class.


    Marcel
     
    Marcel Müller, Jul 24, 2008
    #5
  6. On Jul 24, 6:33 pm, Marcel Müller <>
    wrote:
    > Hi,
    >
    > Darío Griffo schrieb:
    >
    > > class FXToImplement: public B

    >
    > probably you meant
    >
    >    class FXToImplement: virtual public B


    absolutely
     
    Darío Griffo, Jul 24, 2008
    #6
  7. Hi!

    schrieb:
    > Perhaps you are right :-(. Let me write out the problem in better
    > terms.

    [...]

    you wrote exactly the same except that you changed the class and method
    names.

    We still don't know where the dependency of some methodes to the derived
    classes come from. Why must they no be called for some derived classes?
    What happens in that case?


    > As the previous poster suggested I could possibly first have derived
    > classes CarWithTyreX, CarWithTyreY, CarWithTyreZ. And then Car1 is
    > derived from CarWithTyreX, CarWithTyreZ etc.,


    > But the problem with that approach is that the Car has many other
    > features (engine, windows etc.,). And I definitely shouldn't be doing
    > derived classes like CarWithTyreXEngineE1..... That's why I was
    > thinking of just deriving Car1, ... Car4 directly from Car and then
    > applying all other functions appropriately.


    ? - nobody prevents you from implementing the common features in the
    virtual baseclass Car.


    > Also, note that the features aren't just "building blocks" as such.
    > They can be just functions that modify the object's properties in some
    > way.


    That makes no difference in any way.


    Marcel
     
    Marcel Müller, Jul 24, 2008
    #7
  8. Guest

    Marcel Müller wrote:
    > Hi!
    >
    > schrieb:
    > > Perhaps you are right :-(. Let me write out the problem in better
    > > terms.

    > [...]
    >
    > you wrote exactly the same except that you changed the class and method
    > names.
    >
    > We still don't know where the dependency of some methodes to the derived
    > classes come from. Why must they no be called for some derived classes?
    > What happens in that case?
    >
    >


    Well, what I was trying to convey was that a certain type of car can
    only be fitted with a certain type of Tyre. For instance, Car1 is
    compatible only with TyreX and TyreZ. If it attempts to be fitted with
    TyreY then we can of course print a warning and/or throw an
    exception.

    I was wondering if there is a way to entirely prevent Car1 from having
    a way to call the TyreY function. Sorry if I'm being unclear.

    Thanks.
     
    , Jul 24, 2008
    #8
  9. schrieb:
    >> We still don't know where the dependency of some methodes to the derived
    >> classes come from. Why must they no be called for some derived classes?
    >> What happens in that case?

    >
    > Well, what I was trying to convey was that a certain type of car can
    > only be fitted with a certain type of Tyre. For instance, Car1 is
    > compatible only with TyreX and TyreZ.


    Of course, but neither your class is a car nor it have tyres. The
    explanatory power of the paradigm ends here.

    > If it attempts to be fitted with
    > TyreY then we can of course print a warning and/or throw an
    > exception.


    This is no problem. You can easily check this at runtime by overloading
    some of your funtions in some of the derived classes with an empty stub
    that only throws some not_supported_exception.

    > I was wondering if there is a way to entirely prevent Car1 from having
    > a way to call the TyreY function. Sorry if I'm being unclear.


    If you want to check for this at compile time, the compatibility matrix
    has to be part of your class tree. Dario told you how to implement this.


    Marcel
     
    Marcel Müller, Jul 25, 2008
    #9
  10. James Kanze Guest

    On Jul 24, 10:44 pm, wrote:
    > James Kanze wrote:
    > > On Jul 24, 9:08 pm, wrote:
    > > > Say I have a base class B and four derived classes d1, d2, d3, d4. I
    > > > have three functions fx, fy, fz such that:
    > > > fx should only be called by d1, d2
    > > > fy should only be called by d2, d3
    > > > fz should only be called by d1, d3, d4


    > > Then you have a fundamental design problem. Something is
    > > wrong with this scenario. The base class doesn't know about
    > > the derived classes, so it can't impose any restrictions on
    > > a subset of them. And if the restriction comes from the
    > > derived class itself, then the class knows about it, and
    > > will conform to it.


    > > [...]
    > > > Is there any other alternate way to do something like
    > > > this? May be a design pattern that can be adapted to
    > > > handle such a situation?


    > > Perhaps you'd best describe the problem you're trying to
    > > solve, and not just the solution which doesn't work.

    >
    > Perhaps you are right :-(. Let me write out the problem in
    > better terms.


    > Say I have a base class called Car.
    > I have four different cars Car1, Car2, Car3, Car4.
    > There are three types of tyres TyreX, TyreY, TyreZ.
    > TyreX can only "be applied to" Car1, Car2.
    > TyreY only to Car2, Car3.
    > TyreZ only to Car1, Car3, Car4.


    The first question is: why won't all of the tire types work with
    all of the car types? Since you've used suggestive names from a
    domain I vaguely know (I own a car), I can guess: each car has a
    certain number of constraints concerning the tires it can use
    (size being the most obvious one).

    You can solve this either at runtime or through the type system.
    Normally, static verification (type errors) are to be preferred
    to run-time errors, but think about it for awhile: suppose your
    code has a pointer to a Car, and you want to apply some Tire* to
    it. Given that you don't know the actual type of either Car or
    Tire until runtime, how can the compiler tell whether there is a
    mismatch or not.

    The usual solution here is to provide a virtual function in Car,
    which returns the size, etc. (or a list of the sizes, etc.)
    which it can accept for Tire. And of course, a function in Tire
    which returns its size, etc. Which means a runtime check. But
    again, this more or less corresponds to reality: if you go to buy
    tires for your car, you won't go to a tire shop specialized in
    selling only tires for that particular make and model of car;
    you'll go to a general tire shop, pick out a set of tires, and
    then check whether they meet the constraints given in your
    owners manual (a runtime check).

    Note that there can be exceptions: if you can provide a compile
    time check, by all means do so. But this generally means
    defining additional interfaces, derived from Car and Tire (e.g.
    F1RacingCar, F1RacingTires). At that point, code which knows
    it's dealing with F1RacingCars and F1RacingTires can get the
    compile time check, and avoid the runtime one. (But such code
    won't use the basic Car/Tire interface, but rather the derived
    interface.)

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
     
    James Kanze, Jul 25, 2008
    #10
    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. Abhijit Deshpande
    Replies:
    7
    Views:
    11,789
    samualmenon
    Jul 16, 2008
  2. Luca
    Replies:
    2
    Views:
    508
    Rob Williscroft
    Dec 19, 2003
  3. Replies:
    1
    Views:
    419
    myork
    May 23, 2007
  4. Replies:
    1
    Views:
    405
    Victor Bazarov
    May 23, 2007
  5. bgold
    Replies:
    12
    Views:
    1,047
    James Kanze
    Jan 1, 2008
Loading...

Share This Page