Problem accessing protected member of another object

G

gw7rib

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.
 
C

Christopher Swiedler

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
 
A

Alf P. Steinbach

* Christopher Swiedler:
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

Amal

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
 
M

Martin York

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.
 
S

Sergey Prokazov

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.
 

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

Members online

Forum statistics

Threads
473,755
Messages
2,569,534
Members
45,007
Latest member
obedient dusk

Latest Threads

Top