Problem accessing protected member of another object

Discussion in 'C++' started by gw7rib@aol.com, Mar 2, 2008.

  1. Guest

    I'm getting in knots about accessing a protected member. I was under
    the impression that (contrary to what one might expect) access to
    members is worked out on a per-class basis rather than a per-object
    basis. But I'm still having a problem. The following code illustrates
    it:


    void use(int val);

    class Base {
    protected:
    int val;
    public:
    void foo(Base *other);
    };

    void Base::foo(Base *other) {
    use(other -> val); /* Line 1 - works */
    }

    class Derived : public Base {
    public:
    void bar(Base *other);
    };

    void Derived::bar(Base *other) {
    use(val); /* Line 2 - works */
    use(other -> val); /* Line 3 - doesn't work */
    }

    At line 1, I am accessing a member of another object, but this is
    allowed as it is the same class and it is the class, rather than the
    specific object, that matters.

    At line 2, I am accessing a protected member of the base class. This
    works - it is an example of what "protected" means.

    But line 3 does not work, even though I am allowed to access the val
    member of the base class of the same object (see line 2) and (see
    line 1) the actual object shouldn't matter for acessing purposes. What
    is this line doing wrong that the other two aren't?

    Thanks for any explanation.
    Paul.
     
    , Mar 2, 2008
    #1
    1. Advertising

  2. On Mar 2, 12:30 pm, wrote:
    > void use(int val);
    >
    > class Base {
    > protected:
    > int val;
    > public:
    > void foo(Base *other);
    > };
    >
    > void Base::foo(Base *other) {
    > use(other -> val); /* Line 1 - works */
    >
    > }
    >
    > class Derived : public Base {
    > public:
    > void bar(Base *other);
    > };
    >
    > void Derived::bar(Base *other) {
    > use(val); /* Line 2 - works */
    > use(other -> val); /* Line 3 - doesn't work */
    >
    > }


    See http://publib.boulder.ibm.com/infoc.../com.ibm.xlcpp8l.doc/language/ref/cplr129.htm

    I think the problem is that you can access protected members of Base
    only when doing so through a pointer or reference to Derived. When you
    access val in the current object, you're doing so through an implicit
    this, which is a Derived *, so it works. When you access other->val,
    it's a Base *, so it doesn't work. You can cast "other" to a Derived
    *, change the function signature to take a Derived *, or make Derived
    a friend of Base.

    Why that is, I'm not quite sure. My expectations would be that the
    type of the pointer wouldn't matter.

    chris
     
    Christopher Swiedler, Mar 2, 2008
    #2
    1. Advertising

  3. * Christopher Swiedler:
    > On Mar 2, 12:30 pm, wrote:
    >> void use(int val);
    >>
    >> class Base {
    >> protected:
    >> int val;
    >> public:
    >> void foo(Base *other);
    >> };
    >>
    >> void Base::foo(Base *other) {
    >> use(other -> val); /* Line 1 - works */
    >>
    >> }
    >>
    >> class Derived : public Base {
    >> public:
    >> void bar(Base *other);
    >> };
    >>
    >> void Derived::bar(Base *other) {
    >> use(val); /* Line 2 - works */
    >> use(other -> val); /* Line 3 - doesn't work */
    >>
    >> }

    >
    > See http://publib.boulder.ibm.com/infoc.../com.ibm.xlcpp8l.doc/language/ref/cplr129.htm
    >
    > I think the problem is that you can access protected members of Base
    > only when doing so through a pointer or reference to Derived. When you
    > access val in the current object, you're doing so through an implicit
    > this, which is a Derived *, so it works. When you access other->val,
    > it's a Base *, so it doesn't work. You can cast "other" to a Derived
    > *, change the function signature to take a Derived *, or make Derived
    > a friend of Base.
    >
    > Why that is, I'm not quite sure. My expectations would be that the
    > type of the pointer wouldn't matter.


    If you could then you could access protected members of SomeonesDerived
    by deriving from SomeonesBase (that is, the protected members introduced
    in that base class).

    The bad news is that this protection isn't 100%.

    It's only designed to protect against inadvertent access attempts, not
    against serious hacking or in general use of low level language features
    (note: member pointers are a low level language feature).


    Cheers, & hth.,

    - Alf

    --
    A: Because it messes up the order in which people normally read text.
    Q: Why is it such a bad thing?
    A: Top-posting.
    Q: What is the most annoying thing on usenet and in e-mail?
     
    Alf P. Steinbach, Mar 2, 2008
    #3
  4. Amal Guest

    On Mar 3, 1:30 am, wrote:
    > I'm getting in knots about accessing a protected member. I was under
    > the impression that (contrary to what one might expect) access to
    > members is worked out on a per-class basis rather than a per-object
    > basis. But I'm still having a problem. The following code illustrates
    > it:
    >
    > void use(int val);
    >
    > class Base {
    > protected:
    > int val;
    > public:
    > void foo(Base *other);
    > };
    >
    > void Base::foo(Base *other) {
    > use(other -> val); /* Line 1 - works */
    >
    > }
    >
    > class Derived : public Base {
    > public:
    > void bar(Base *other);
    > };
    >
    > void Derived::bar(Base *other) {
    > use(val); /* Line 2 - works */
    > use(other -> val); /* Line 3 - doesn't work */
    >
    > }
    >
    > At line 1, I am accessing a member of another object, but this is
    > allowed as it is the same class and it is the class, rather than the
    > specific object, that matters.
    >
    > At line 2, I am accessing a protected member of the base class. This
    > works - it is an example of what "protected" means.
    >
    > But line 3 does not work, even though I am allowed to access the val
    > member of the base class of the same object (see line 2) and (see
    > line 1) the actual object shouldn't matter for acessing purposes. What
    > is this line doing wrong that the other two aren't?
    >
    > Thanks for any explanation.
    > Paul.


    -> void Derived::bar(Base *other) {
    -> use(val); /* Line 2 - works */
    -> use(other -> val); /* Line 3 - doesn't work */
    ->
    -> }

    Here in the member function of derived class Base is considered
    like any other class. It doesn't make any difference if class Derived
    is derived from Base. You cannot access the protected member by
    directly referring from an object. So it is not an artifact rather a
    perfect implementation.

    But you can access the other->val in case if the bar was
    accepting a Derived*. This is how copy constructor works.

    And for an example let us derive another class from Base.

    class AnotherDerived:public Base
    {
    /*.....*/
    }
    AnotherBase AnotherBaseobj;

    Now you can cast AnotherBaseobj down to its Base* and pass it to
    the member of Derived::bar. Does it make sense? Its invalid for sure.

    To detail see the below program.

    class Base
    {
    protected:
    int val;
    public:
    };

    class Derived:public Base
    {
    public:
    void foo( Base* obj )
    {
    std::cout<<obj->val; // This line will generate error unconditional
    to the way in which class Derived is -derived- from class Base
    }
    };

    class AnotherDerived:public Base
    {
    };

    int main()
    {
    Derived Obj1;
    AnotherDerived Obj2;
    Obj1.foo( &Obj2 );
    return 0;
    }

    I guess this answers why this doesn't work in the way you
    expected.

    Thanks a lot,
    Amal P
     
    Amal, Mar 3, 2008
    #4
  5. Martin York Guest

    On Mar 2, 12:30 pm, wrote:
    > I'm getting in knots about accessing a protected member. I was under
    > the impression that (contrary to what one might expect) access to
    > members is worked out on a per-class basis rather than a per-object
    > basis. But I'm still having a problem. The following code illustrates
    > it:
    >
    > void use(int val);
    >
    > class Base {
    > protected:
    > int val;
    > public:
    > void foo(Base *other);
    > };
    >
    > void Base::foo(Base *other) {
    > use(other -> val); /* Line 1 - works */
    >
    > }
    >
    > class Derived : public Base {
    > public:
    > void bar(Base *other);
    > };
    >
    > void Derived::bar(Base *other) {
    > use(val); /* Line 2 - works */
    > use(other -> val); /* Line 3 - doesn't work */
    >
    > }
    >
    > At line 1, I am accessing a member of another object, but this is
    > allowed as it is the same class and it is the class, rather than the
    > specific object, that matters.
    >
    > At line 2, I am accessing a protected member of the base class. This
    > works - it is an example of what "protected" means.
    >
    > But line 3 does not work, even though I am allowed to access the val
    > member of the base class of the same object (see line 2) and (see
    > line 1) the actual object shouldn't matter for acessing purposes. What
    > is this line doing wrong that the other two aren't?
    >
    > Thanks for any explanation.
    > Paul.



    A class is automatically a friend of itself.
    That is why line 1 is working.

    Because a class is a friend of itself then any object of class A can
    access all members (private and protected) of another object of class
    A.

    Note friendship is not inherited. So children of A have no rights to
    access the member of another object of type A. Though the protected
    status allows them to access members of the base class that are apart
    of the same object.
     
    Martin York, Mar 3, 2008
    #5
  6. > A class is automatically a friend of itself.
    > That is why line 1 is working.


    Basically, you are right.
    When you declare something like "class A : public B {}", compiler
    copies public and protected sections of A to the beginning of B.
    Actually compiler has some other things to do, particularly if base
    class is polymorphic, but let's omit them for clarity.


    Lets have a look at an example:

    class Base{
    protected:
    int val;
    public:
    void foo(Base *other);
    };


    class Derived_1
    {
    protected:
    int val;
    public:
    void foo(Base *other);
    };

    class Derived_2 : public Base
    {
    };

    Compiler will generate the same code for Derived_1 and Derived_2
    objects. Derived_1-type objects and Base-type objects are not related
    each other. The same we can say about Derived_2-type objects.
    If you need functionality of the existing class in your brand new
    class, you don't need to copy-paste it by yourself, you can use
    inheritance and compiler will gladly copy-paste it for you.
     
    Sergey Prokazov, Mar 4, 2008
    #6
    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. Steven T. Hatton
    Replies:
    2
    Views:
    426
    tom_usenet
    Aug 16, 2004
  2. Siemel Naran
    Replies:
    4
    Views:
    824
    Micah Cowan
    Jan 12, 2005
  3. Joseph Paterson
    Replies:
    4
    Views:
    1,040
    Joseph Paterson
    Jun 28, 2007
  4. blangela
    Replies:
    8
    Views:
    680
    Erik Wikström
    Sep 26, 2008
  5. K. Frank
    Replies:
    8
    Views:
    664
    K. Frank
    Mar 22, 2012
Loading...

Share This Page