class acces scope weirdness

O

olanglois

Hi,

I am not sure if I have found a compiler bug (I am using VC++.NET2003)
or if this is the correct behavior defined by the language but I am
sure someone can clear up my confusion. Suppose the following:

class Base
{
protected:
int x;
};

class Derived : public Base
{
public:
void A( const Derived &d )
{ x = d.x; // Ok }
void B( const Base &b )
{ x = b.x; //Error: cannot access protected member declared in
class 'Base' }
};

What is the problem with B()? What should I change in Derived to fix
the problem? The best thing I came up is by modifying Base like this:

class Base
{
protected:
void SetX(const Base &b) { x = b.x; }
int x;
};

and call SetX from B().

Thanks,
Olivier Langlois
http://www3.sympatico.ca/olanglois


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
 
V

Victor Bazarov

I am not sure if I have found a compiler bug (I am using VC++.NET2003)
No.

or if this is the correct behavior defined by the language
Yes.

but I am
sure someone can clear up my confusion. Suppose the following:

class Base
{
protected:
int x;
};

class Derived : public Base
{
public:
void A( const Derived &d )
{ x = d.x; // Ok }
void B( const Base &b )
{ x = b.x; //Error: cannot access protected member declared in
class 'Base' }

Correct behaviour.
};

What is the problem with B()? What should I change in Derived to fix
the problem?

Nothing. The derived class cannot access protected members in objects
of other than its own type.
The best thing I came up is by modifying Base like this:

class Base
{
protected:
void SetX(const Base &b) { x = b.x; }
int x;
};

and call SetX from B().

That's it. As you can see, you can't do it in Derived.

V
 
J

Jim Langston

Victor Bazarov said:
Correct behaviour.


Nothing. The derived class cannot access protected members in objects
of other than its own type.

I was curious about this and looked up the protected keyword in MSDN and
came across this:

The protected keyword specifies access to class members in the member-list
up to the next access specifier (public or private) or the end of the class
definition. Class members declared as protected can be used only by the
following:

Member functions of the class that originally declared these members.
Friends of the class that originally declared these members.
Classes derived with public or protected access from the class that
originally declared these members.
Direct privately derived classes that also have private access to protected
members.

Is MSDN wrong or am I reading it wrong? It seems to state that "...can be
used only by the following: ... Classes derived with public or protected
access from the class that originally declared these members..."

Isn't that the case here? Isn't Derived deriving with public access from
Base? I'm not sure since I never use protected.
 
V

Victor Bazarov

Jim said:
I was curious about this and looked up the protected keyword in MSDN
and came across this:

The protected keyword specifies access to class members in the
member-list up to the next access specifier (public or private) or
the end of the class definition. Class members declared as protected
can be used only by the following:

Member functions of the class that originally declared these members.
Friends of the class that originally declared these members.
Classes derived with public or protected access from the class that
originally declared these members.
Direct privately derived classes that also have private access to
protected members.

Is MSDN wrong or am I reading it wrong?

MSDN's description is incomplete. Does it mean it's wrong? I don't
know.

An object can only access protected members of the object of its own
type. From 11.5/1:

"When a friend or a member function of a derived class references
a protected nonstatic member function or
protected nonstatic data member of a base class, an access check
applies in addition to those described earlier
in clause 11.102) Except when forming a pointer to member (5.3.1),
the access must be through a
pointer to, reference to, or object of the derived class itself
(or any class derived from that class) (5.2.5)."

See the "must be through a pointer to, reference to, or object of
the defiend class itself"?
It seems to state that
"...can be used only by the following: ... Classes derived with
public or protected access from the class that originally declared
these members..."
Isn't that the case here? Isn't Derived deriving with public access
from Base? I'm not sure since I never use protected.

It's not the case here. The object '*this' is trying to access the
'x' protected member in an object of type 'Base', IOW in an object
of another type than its own.

V
 
M

Mehturt

Hi,

I am not sure if I have found a compiler bug (I am using VC++.NET2003)
or if this is the correct behavior defined by the language but I am
sure someone can clear up my confusion. Suppose the following:

class Base
{
protected:
int x;
};

class Derived : public Base
{
public:
void A( const Derived &d )
{ x = d.x; // Ok }
void B( const Base &b )
{ x = b.x; //Error: cannot access protected member declared in
class 'Base' }
};

What is the problem with B()? What should I change in Derived to fix
the problem? The best thing I came up is by modifying Base like this:

class Base
{
protected:
void SetX(const Base &b) { x = b.x; }
int x;
};

and call SetX from B().

Thanks,
Olivier Langlois
http://www3.sympatico.ca/olanglois

I think the SetX() should work only if it's made public. Same with the
x attribute.


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
 
T

Thomas Maeder

I am not sure if I have found a compiler bug (I am using VC++.NET2003)
or if this is the correct behavior defined by the language but I am
sure someone can clear up my confusion. Suppose the following:

The compiler is correct in this regard.

class Base
{
protected:
int x;
};

class Derived : public Base
{
public:
void A( const Derived &d )
{ x = d.x; // Ok }
void B( const Base &b )
{ x = b.x; //Error: cannot access protected member declared in
class 'Base' }
};

What is the problem with B()? What should I change in Derived to fix
the problem?

Nothing.

If class Derived were allowed to access data member x of any Base object, the
access control provided by protected could be subverted by deriving another
class from Base just for this purpose.

I.e.

void foo1(Base &b)
{
b.x; // oops, data member x is protected
}

So let's do

void foo2(Base &b)
{
struct MyHack : Base // derived from Base to hijack access to B::x
{
static void bar(Base &b)
{
b.x; // would be correct if MyHack could access x of any Base object
}
};

MyHack::bar(b);
}


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
 
C

cs2991

class Derived : public Base
{
public:
void A( const Derived &d )
{ x = d.x; // Ok }
void B( const Base &b )
{ x = b.x; //Error: cannot access protected member declared in
class 'Base' }

};

What is the problem with B()? What should I change in Derived to fix
the problem? The best thing I came up is by modifying Base like this:

The compiler is correct. When a base class has protected data, it
only allows a derived type to access protected data of instances of
that derived type. It does not grant unrestricted access to the
protected data of EVERY derived type. When you only have a reference
to the base, the actual object might not be a Derived, but maybe
something else that is derived from Base. Derived should NOT have
access to another derived types's protected data simply because they
both have the same base class.


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
 
A

Alf P. Steinbach

* (e-mail address removed):
Hi,

I am not sure if I have found a compiler bug (I am using VC++.NET2003)
or if this is the correct behavior defined by the language but I am
sure someone can clear up my confusion. Suppose the following:

class Base
{
protected:
int x;
};

class Derived : public Base
{
public:
void A( const Derived &d )
{ x = d.x; // Ok }
void B( const Base &b )
{ x = b.x; //Error: cannot access protected member declared in
class 'Base' }
};

What is the problem with B()?

The standard prohibits that access.

Reason: if it were allowed, all you'd need to do to access protected
class X members in any object would be to derive a class from X.

What should I change in Derived to fix the problem?

It's not a problem, it's a feature... ;-)

Seriously, you haven't described the /problem/ you're trying to solve,
only a flawed attempt at a solution.

But one may speculate that the problem is how to initialize members of
Base, and if so, then the answer is, in general, to provide an
appropriate Base constructor, or more.

--
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?

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
 
R

Russell Hind

Hi,

I am not sure if I have found a compiler bug (I am using VC++.NET2003)
or if this is the correct behavior defined by the language but I am
sure someone can clear up my confusion. Suppose the following:

class Base
{
protected:
int x;
};

class Derived : public Base
{
public:
void A( const Derived &d )
{ x = d.x; // Ok }
void B( const Base &b )
{ x = b.x; //Error: cannot access protected member declared in
class 'Base' }
};

What is the problem with B()?

I'm not sure, but you could have this structure:

class Base
{
protected:
int x;
};

class Dervied1 : public Base
{
};

class Dervied2: public Base
{
};

You could then pass an instance of Dervied2 as a 'Base' in to the
constructor of derived one, but they are off different hierachies, so
you'd have the case where Dervied1 was trying to access Dervied2::x
which I don't think is allowed so I think you can only access the
protected members of base if you have base as a Dervied1 type, i.e. same
type as you.

I've seen this (or something very similar with BCB6) so I assumed the
compiler was correct but I may be wrong on that.

Cheers

Russell

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
 
S

Salt_Peter

Hi,

I am not sure if I have found a compiler bug (I am using VC++.NET2003)
or if this is the correct behavior defined by the language but I am
sure someone can clear up my confusion. Suppose the following:

class Base
{
protected:
int x;
};

class Derived : public Base
{
public:
void A( const Derived &d )
{ x = d.x; // Ok }
void B( const Base &b )
{ x = b.x; //Error: cannot access protected member declared in
class 'Base' }
};

What is the problem with B()? What should I change in Derived to fix
the problem? The best thing I came up is by modifying Base like this:

There is no problem, what you see is what you get. the parameter
references b, d are not part of the construct, its just a potential
object reference. Treat b, d as what they really are, an external
object. As you found out, the only way you can access x is through a
Derived object(access: protected).

Also, the use of Base::x only applies to this instance of the Derived
class. If you need a Derived object to provide read-access to its
protected x:

int Derived::getx() const
{
return Base:x;
}

The Base:: is not needed but it'll make the code readable.
class Base
{
protected:
void SetX(const Base &b) { x = b.x; }
int x;
};

and call SetX from B().

Look at void Derived::A(...), wouldn't you be better off with a copy
ctor that performs a deep copy? Interestingly enough, that would work
with x declared as having private access (hint).

Same goes with void Derived::B(...), you could write a conversion ctor
or provide an operator= or both that take a Base parameter.

Just because you have a daughter named Julie that has blond hair and the
neighbour also has a blond Julie doesn't mean the neighbour's daughter
also gets the key to the house. es cosa nostra.

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
 

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,772
Messages
2,569,593
Members
45,109
Latest member
JanieMalco
Top