Private access in an implementation still allows public access in an abstract interface

Discussion in 'C++' started by tron.thomas@verizon.net, Feb 26, 2006.

  1. Guest

    Please consider the following code:

    class Abstract
    {
    public:
    virtual ~Abstract() {}
    virtual void Method() = 0;
    };

    class Concrete : public virtual Abstract
    {
    private:
    virtual void Method() {}
    };

    void UseAbstract()
    {
    Concrete concrete;
    Abstract& abstract = concrete;

    abstract.Method();
    }


    The implementation for Abstract::Method provided in the Concrete class
    is private even though the declaration of the method is public in the
    derived base class. Yet, compiling the code on three different
    compilers produces no errors or warnings. I think many developer might
    find this surprising and puzzling. I, myself, am not sure what to
    think of it.

    The end effect is that the implementation for the Abstract class works
    as expected. An instance of Concrete can be used as an Abstract
    instance and it works as expected with respect to the Abstract
    interface. Method is public for Abstract and can be accessed just
    fine, even though it is private with respect to its Concrete
    implementation.

    However, it seems that there is something wrong, or at least worrisome
    about the fact that this can be done.

    What can people say about the correctness of this code?
    If it is correct, what are the reasons classes are allow to behave this
    way?
     
    , Feb 26, 2006
    #1
    1. Advertising

  2. John Carson Guest

    <> wrote in message
    news:
    > Please consider the following code:
    >
    > class Abstract
    > {
    > public:
    > virtual ~Abstract() {}
    > virtual void Method() = 0;
    > };
    >
    > class Concrete : public virtual Abstract
    > {
    > private:
    > virtual void Method() {}
    > };
    >
    > void UseAbstract()
    > {
    > Concrete concrete;
    > Abstract& abstract = concrete;
    >
    > abstract.Method();
    > }
    >
    >
    > The implementation for Abstract::Method provided in the Concrete class
    > is private even though the declaration of the method is public in the
    > derived base class. Yet, compiling the code on three different
    > compilers produces no errors or warnings. I think many developer
    > might find this surprising and puzzling. I, myself, am not sure what
    > to think of it.


    What object a reference refers to cannot always be known at compile time but
    may instead only be known at run time. Access rules are enforced at compile
    time, so access rules cannot depend on the object referred to. Instead, they
    depend on the type of the reference, since this is known at compile time.
    The type of abstract is "reference to Abstract" and Method() is public in
    Abstract. Accordingly, access must be allowed.

    --
    John Carson
     
    John Carson, Feb 26, 2006
    #2
    1. Advertising

  3. Guest

    John Carson wrote:
    >
    > What object a reference refers to cannot always be known at compile time but
    > may instead only be known at run time. Access rules are enforced at compile
    > time, so access rules cannot depend on the object referred to. Instead, they
    > depend on the type of the reference, since this is known at compile time.
    > The type of abstract is "reference to Abstract" and Method() is public in
    > Abstract. Accordingly, access must be allowed.
    >
    > --
    > John Carson


    Thanks John. That makes sense.
     
    , Feb 26, 2006
    #3
  4. Neil Cerutti Guest

    On 2006-02-26, <> wrote:
    > Please consider the following code:
    >
    > class Abstract
    > {
    > public:
    > virtual ~Abstract() {}
    > virtual void Method() = 0;
    > };
    >
    > class Concrete : public virtual Abstract
    > {
    > private:
    > virtual void Method() {}
    > };
    >
    > void UseAbstract()
    > {
    > Concrete concrete;
    > Abstract& abstract = concrete;
    >
    > abstract.Method();
    > }
    >
    >
    > The implementation for Abstract::Method provided in the Concrete class
    > is private even though the declaration of the method is public in the
    > derived base class. Yet, compiling the code on three different
    > compilers produces no errors or warnings. I think many developer might
    > find this surprising and puzzling. I, myself, am not sure what to
    > think of it.


    It is this way because the alternative seemed worse. The C++ designers
    deemed it would be horrible if changing the access specification of a
    member function somewhere in your class hierarchy could alter the
    resolution of a virtual function call, or cause your program to no
    longer compile. Consider multiple inheritance:

    class B {
    public:
    virtual void foo();
    };

    class X: public B {
    private:
    void foo();
    };

    class Y: public B {
    public:
    void foo();
    };

    class Fubar: public X, Y {
    public:
    void foo();
    };

    In this hierarchy, under a rule that made the private foo in X
    inaccessible, there would be no ambiguity in the following call in
    function fnagn. It would have to resolve to the public override in B.

    void fnagn(Fubar* f)
    {
    f->foo();
    }

    But if the access specification of foo in X were then changed to
    public, suddenly your code would not even compile.

    So the actual rules make your code more robust, in theory. The call to
    foo in fnagn is ambiguous, despite foo in X being private.

    --
    Neil Cerutti
     
    Neil Cerutti, Feb 27, 2006
    #4
  5. Phlip Guest

    Neil Cerutti wrote:

    > But if the access specification of foo in X were then changed to
    > public, suddenly your code would not even compile.


    The other odious alternative enforces access at runtime. That would add
    extra opcodes to all the virtual functions that don't need them.

    The OP should research Design Patterns. Sometimes a method's access is a
    valid technique.

    --
    Phlip
    http://www.greencheese.org/ZeekLand <-- NOT a blog!!!
     
    Phlip, Feb 27, 2006
    #5
  6. Phlip Guest

    Phlip wrote:

    > Neil Cerutti wrote:
    >
    >> But if the access specification of foo in X were then changed to
    >> public, suddenly your code would not even compile.

    >
    > The other odious alternative enforces access at runtime. That would add
    > extra opcodes to all the virtual functions that don't need them.
    >
    > The OP should research Design Patterns. Sometimes


    changing!

    > a method's access is a
    > valid technique.


    --
    Phlip
    http://www.greencheese.org/ZeekLand <-- NOT a blog!!!
     
    Phlip, Feb 27, 2006
    #6
  7. Neil Cerutti Guest

    On 2006-02-27, Neil Cerutti <> wrote:
    > On 2006-02-26, <> wrote:
    > It is this way because the alternative seemed worse. The C++ designers
    > deemed it would be horrible if changing the access specification of a
    > member function somewhere in your class hierarchy could alter the
    > resolution of a virtual function call, or cause your program to no
    > longer compile. Consider multiple inheritance:
    >
    > class B {
    > public:
    > virtual void foo();
    > };
    >
    > class X: public B {
    > private:
    > void foo();
    > };
    >
    > class Y: public B {
    > public:
    > void foo();
    > };
    >
    > class Fubar: public X, Y {
    > public:
    > void foo();
    > };
    >
    > In this hierarchy, under a rule that made the private foo in X
    > inaccessible, there would be no ambiguity in the following call in
    > function fnagn. It would have to resolve to the public override in B.
    >
    > void fnagn(Fubar* f)
    > {
    > f->foo();
    > }
    >


    It seems people got the point, but there were errors in my example code.

    Fubar should not declare a function foo, and fnagn should receive
    pointer to B.

    > But if the access specification of foo in X were then changed to
    > public, suddenly your code would not even compile.
    >
    > So the actual rules make your code more robust, in theory. The call
    > to foo in fnagn is ambiguous, despite foo in X being private.



    --
    Neil Cerutti
    You can't give him that cutback lane. He's so fast, and he sees
    it so well. He can also run away from you if he gets a little
    bit of crack. --Dick Lebeau
     
    Neil Cerutti, Mar 1, 2006
    #7
  8. Guest

    wrote:
    > Please consider the following code:
    >
    > class Abstract
    > {
    > public:
    > virtual ~Abstract() {}
    > virtual void Method() = 0;
    > };
    >
    > class Concrete : public virtual Abstract
    > {
    > private:
    > virtual void Method() {}
    > };
    >
    > void UseAbstract()
    > {
    > Concrete concrete;
    > Abstract& abstract = concrete;
    >
    > abstract.Method();
    > }
    >
    >
    > The implementation for Abstract::Method provided in the Concrete class
    > is private even though the declaration of the method is public in the
    > derived base class. Yet, compiling the code on three different
    > compilers produces no errors or warnings. I think many developer might
    > find this surprising and puzzling. I, myself, am not sure what to
    > think of it.
    >
    > The end effect is that the implementation for the Abstract class works
    > as expected. An instance of Concrete can be used as an Abstract
    > instance and it works as expected with respect to the Abstract
    > interface. Method is public for Abstract and can be accessed just
    > fine, even though it is private with respect to its Concrete
    > implementation.
    >
    > However, it seems that there is something wrong, or at least worrisome
    > about the fact that this can be done.
    >
    > What can people say about the correctness of this code?
    > If it is correct, what are the reasons classes are allow to behave this
    > way?


    The rule of thumb is that only the names of things can be made private,
    not the things themselves. I think the main reason for this is that
    it's
    not possible at (least currently) to have ironclad protection of
    members
    that could not be defeated with casts, and have no run-time overhead.

    In the particular example you give, I think there are cases where it
    could actually be useful. The purpose of private is for the designer
    of the class to prevent class users from creating undesired
    dependencies
    on cretain specifics of the class definition. What the above code is
    saying is "don't write any code for Concrete instances using 'method()'
    that would not also work for all instances of Abstract".
     
    , Mar 1, 2006
    #8
    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. Charles A. Lackman
    Replies:
    1
    Views:
    1,423
    smith
    Dec 8, 2004
  2. SpamProof
    Replies:
    0
    Views:
    618
    SpamProof
    Oct 21, 2003
  3. qazmlp
    Replies:
    19
    Views:
    818
    Daniel T.
    Feb 4, 2004
  4. DaveLessnau
    Replies:
    3
    Views:
    443
    Howard
    May 16, 2005
  5. Replies:
    1
    Views:
    1,562
    =?ISO-8859-1?Q?Arne_Vajh=F8j?=
    Sep 11, 2006
Loading...

Share This Page