Possible encapsulation violation in C++

Discussion in 'C++' started by Naresh Agarwal, Mar 31, 2005.

  1. Hi

    Class B
    {
    public :

    virtual void foo()
    {
    // some impl
    }
    }

    Class D : public B
    {
    private :

    void foo()
    {
    // some impl
    }
    }

    void main()
    {
    B *b = new D();
    b->foo();
    }

    This program works fine!

    So basically, we are able to access a private function of derived class
    using a base class pointer. Why is it allowed in C++? Isn't it
    voilation of encapsulation???

    thanks & regards,
    Naresh Agarwal
    Naresh Agarwal, Mar 31, 2005
    #1
    1. Advertising

  2. Naresh Agarwal

    Hang Dog Guest

    Naresh Agarwal wrote:

    > Isn't it
    > voilation of encapsulation???
    >


    No all you have done is fuxored the is-a relationship.
    Hang Dog, Mar 31, 2005
    #2
    1. Advertising

  3. Naresh Agarwal

    chintoo Guest

    Hang Dog wrote:
    > Naresh Agarwal wrote:
    >
    > > Isn't it
    > > voilation of encapsulation???
    > >

    >
    > No all you have done is fuxored the is-a relationship.


    If it is all about is-a relationship, then why does compiler give error
    if we allocate an object of D ( sy d)on stack and say d.foo() . Clearly
    its a mix-up.
    Effectively the end result points to inconsistent behaviour. If access
    specifier was a part of function signature then this problem wouldnt
    arise.
    chintoo, Mar 31, 2005
    #3
  4. Naresh Agarwal

    lilburne Guest

    chintoo wrote:

    > Hang Dog wrote:
    >
    >>Naresh Agarwal wrote:
    >>
    >>
    >>>Isn't it
    >>>voilation of encapsulation???
    >>>

    >>
    >>No all you have done is fuxored the is-a relationship.

    >
    >
    > If it is all about is-a relationship, then why does compiler give error
    > if we allocate an object of D ( sy d)on stack and say d.foo() . Clearly
    > its a mix-up.



    Because as a D the method is private but as a B it is public. The B
    behaviour is consitent with B, that D behaviour is consitent with it
    being a D. The problem is that D is not a B but derived incorrectly.
    This is a design issue not a language issue.


    > Effectively the end result points to inconsistent behaviour. If access
    > specifier was a part of function signature then this problem wouldnt
    > arise.
    >


    There are many ways in which you can get inconsitent behaviour. For
    example in one of our old class heirarchies we have a virtual reset()
    method. The intent of the method was to reset the instance to the state
    it would be in if it were default constructed. A colleague decide this
    would be a nice method name for a function which reset an iterator
    within a derived class. Result inconsitent behaviour and fuxored is-a
    relationship. This is also an example of why virtual methods should not
    be public.
    lilburne, Mar 31, 2005
    #4
  5. Naresh Agarwal wrote:

    > Hi
    >
    > Class B


    class B

    > {
    > public :
    >
    > virtual void foo()
    > {
    > // some impl
    >
    > }


    };

    >
    > Class D : public B


    class

    > {
    > private :
    >
    > void foo()
    > {
    > // some impl
    > }


    };

    >
    > void main()


    int main()

    > {
    > B *b = new D();
    > b->foo();
    > }
    >
    > This program works fine!
    >
    > So basically, we are able to access a private function of derived class
    > using a base class pointer. Why is it allowed in C++? Isn't it
    > voilation of encapsulation???



    You can think of it as an intention foo() to be accessible when a D object is treated as a
    B object, and not accessible if it is treated as a D object.


    To do what you want, you can use private inheritance:



    class B
    {
    public :

    virtual void foo()
    {
    // some impl
    }
    };

    class D : private B
    {
    private :

    void foo()
    {
    // some impl
    }
    };

    int main()
    {
    B *b = new D();
    b->foo();
    }


    C:\c\temp.cpp In function `int main()':
    23 C:\c\temp.cpp `B' is an inaccessible base of `D'



    --
    Ioannis Vranos

    http://www23.brinkster.com/noicys
    Ioannis Vranos, Mar 31, 2005
    #5
  6. Naresh Agarwal

    ulrich Guest

    On 31 Mar 2005 05:21:36 -0800, chintoo <> wrote:

    >
    > Hang Dog wrote:
    >> Naresh Agarwal wrote:
    >>
    >> > Isn't it
    >> > voilation of encapsulation???
    >> >

    >>
    >> No all you have done is fuxored the is-a relationship.

    >
    > If it is all about is-a relationship, then why does compiler give error
    > if we allocate an object of D ( sy d)on stack and say d.foo() .


    because here

    D d;
    d.foo();

    tries to call D::foo(), which is a private member of D and thus not
    accessible.
    ulrich, Mar 31, 2005
    #6
  7. lilburne wrote:

    >
    > Because as a D the method is private but as a B it is public. The B
    > behaviour is consitent with B, that D behaviour is consitent with it
    > being a D. The problem is that D is not a B but derived incorrectly.
    > This is a design issue not a language issue.
    >


    Actually, it /should/ be a language issue. Access modifiers in Java are
    part of the function signature for example. From your standpoint, you
    can make everything a design issue.

    As to the "D is not a B":

    class Bird
    {
    public:
    virtual void fly() = 0;
    };

    class Blackbird
    {
    public:
    virtual void fly() { // fly in some way }
    };

    class Penguin
    {
    private:
    virtual void fly() {}
    };

    A Penguin's wings may be too small to fly. But it's a bird afterall. I
    know this is not the cleanest way to express that PenguinS can't fly,
    but you get the point.

    > There are many ways in which you can get inconsitent behaviour. For
    > example in one of our old class heirarchies we have a virtual reset()
    > method. The intent of the method was to reset the instance to the state
    > it would be in if it were default constructed. A colleague decide this
    > would be a nice method name for a function which reset an iterator
    > within a derived class. Result inconsitent behaviour and fuxored is-a
    > relationship. This is also an example of why virtual methods should not
    > be public.
    >


    Which proves what? One more reason for making it a language issue.


    --
    Matthias Kaeppler
    Matthias Kaeppler, Mar 31, 2005
    #7
  8. Matthias Kaeppler wrote:

    > class Blackbird

    : public Bird
    > {
    > public:
    > virtual void fly() { // fly in some way }
    > };
    >
    > class Penguin

    : public Bird
    > {
    > private:
    > virtual void fly() {}
    > };



    Sorry.

    --
    Matthias Kaeppler
    Matthias Kaeppler, Mar 31, 2005
    #8
  9. Naresh Agarwal

    Jerry Coffin Guest

    Matthias Kaeppler wrote:

    [ ... ]

    > As to the "D is not a B":
    >
    > class Bird
    > {
    > public:
    > virtual void fly() = 0;
    > };
    >
    > class Blackbird
    > {
    > public:
    > virtual void fly() { // fly in some way }
    > };
    >
    > class Penguin
    > {
    > private:
    > virtual void fly() {}
    > };
    >
    > A Penguin's wings may be too small to fly. But it's a bird afterall.


    No it's not -- at least by your definition. Inclusion of "fly" as a
    member of the base class specifies a class invariant -- specifically
    that "all birds can fly." By that definition, a Penguin is NOT a bird.

    Ultimately, you have two choices: either all birds can fly, in which
    case you've defined "bird" to exclude Penguins, Ostriches, Emus, etc.,
    or else some birds can't fly, in which case your base class is simply
    wrong.

    [ ... problems elided ]

    > Which proves what? One more reason for making it a language issue.


    I don't see a way to enforce this in a meaningful way at the language
    level. You've simply specified a class invariant, and then violated it.
    Ultimately, it seems to me that diagnosing such things requires
    knowledge of the meaning of identifier involved to verify that (for
    example) when you claim that all birds can fly that it's really
    correct.

    Even if that was possible, we probably wouldn't want it anyway. In most
    cases, we're not looking for things that are necessarily true in
    general, but simply that they're true to the extent necesary for the
    job we're doing. As such, even if the compiler could enforce that our
    names were completely accurate, we probably wouldn't want it to anyway.

    --
    Later,
    Jerry.

    The universe is a figment of its own imagination.
    Jerry Coffin, Apr 1, 2005
    #9
  10. Jerry Coffin wrote:
    > I don't see a way to enforce this in a meaningful way at the language
    > level.


    Java does, though indirectly. Access modifiers in Java are part of the
    function signature, so a "private" fly() would /not/ be the allowed way
    to implement the base class method:

    interface Base {
    public void fly();
    }

    class Derived implements Base {
    private void fly() {}
    }


    override.java:6: fly() in Derived cannot implement fly() in Base;
    attempting to assign weaker access privileges; was public
    private void fly() {}

    --
    Matthias Kaeppler
    Matthias Kaeppler, Apr 1, 2005
    #10
  11. Naresh Agarwal

    darkstorm Guest

    > No all you have done is fuxored the is-a relationship.

    I didn't get what you mean..please explain
    darkstorm, Apr 1, 2005
    #11
  12. Naresh Agarwal

    Jerry Coffin Guest

    Matthias Kaeppler wrote:
    > Jerry Coffin wrote:
    > > I don't see a way to enforce this in a meaningful way at the
    > > language level.

    >
    > Java does, though indirectly. Access modifiers in Java are part
    > of the function signature, so a "private" fly() would /not/ be
    > the allowed way to implement the base class method:


    Unfortunately, this is the opposite of what I was talking about. I was
    talking about it preventing you from putting a "fly" member in a class
    named "bird" in the first place. This makes you claim that a Penguin
    really CAN fly.

    Java is enforcing consistent lies, not honesty.

    --
    Later,
    Jerry.

    The universe is a figment of its own imagination.
    Jerry Coffin, Apr 1, 2005
    #12
  13. Matthias Kaeppler wrote:
    > Jerry Coffin wrote:
    >
    >> I don't see a way to enforce this in a meaningful way at the language
    >> level.

    >
    >
    > Java does, though indirectly. Access modifiers in Java are part of the
    > function signature, so a "private" fly() would /not/ be the allowed way
    > to implement the base class method:


    That is, in a sense, a hack of what you really want though. NOt all birds can
    fly and a Penguin having a method to fly, regardless of access, just seems
    wrong. The fact tht not all birds can fly means having a public fly() method
    in he Bird class is even worse. A better way would be like this:

    class Bird {
    public:
    virtual ~Bird();
    };

    class FlyingBird : public Bird {
    public:
    virtual void fly() = 0;
    };

    class Blackbird : public FlyingBird {
    public:
    void fly();
    }

    class Penguin : public Bird {
    ....
    }

    Now you have an IS-A rleationship between all bird-types as Bird, and one for
    flying birds as FlyingBird. This then allows you to do:

    void flyBird(Bird& b)
    {
    // attempt to cast b to a FLyingBird. If not able to fly, throw std::bad_cast
    FlyingBird& fb = dynamic_cast<FlyingBird&>(b);
    fb.fly();
    }
    Kurt Stutsman, Apr 1, 2005
    #13
    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. Andrew FPGA
    Replies:
    14
    Views:
    1,136
    Jim Lewis
    Oct 5, 2005
  2. Jack
    Replies:
    1
    Views:
    465
  3. Wayne Berke
    Replies:
    0
    Views:
    383
    Wayne Berke
    Sep 19, 2003
  4. Tim Jowers

    obj,fn,parms encapsulation in java

    Tim Jowers, Sep 13, 2004, in forum: Java
    Replies:
    1
    Views:
    370
    Alan Meyer
    Sep 13, 2004
  5. Replies:
    1
    Views:
    10,413
    kj12345
    Mar 1, 2005
Loading...

Share This Page