discussion of protected in Lippman

T

t

Lippman's C++ Primer, 4th ed., p562, dicussion of protected members
seems to be wrong, unless I am misinterpreting things. He says:

"A derived class object may access the protected members of its base
class only through a derived object. The derived class has no special
access to the protected members of base type objects."

He gives the following example:

=========================================================
class Item_base
{
public:
// stuff omitted
protected:
double price;
private:
std::string isbn;
};

class Bulk_item : public Item_base {
// stuff omitted
};

void Bulk_item::memfcn(const Bulk_item&d, const Item_Base& b)
{
// attempt to use protected member
double ret = price; // ok: uses this->price
ret = d.price; // ok: uses price from a Bulk_item object
ret = b.price; // error: no access to price from an Item_base
}

=========================================================

Am I right?
 
T

t

Nevermind. I just tried it (which I should have done before
posting). Lippman is correct.

I was confusing:

(1) how a derived class inherits all the members of the base class and
can use the public and protected members, yet cannot use the inherited
private members; in particular, an inherited protected member becomes
a member of the derived class itself;

and

(2) if a derived class object has access to a base class object (this
doesn't include the base class PART of a derived class object), then
it can only access the base class object's public members and not its
protected or private members.

===

Is this correct? This was a bit too subtle for me to catch at first.
 
N

Neelesh Bodas

Lippman's C++ Primer, 4th ed., p562, dicussion of protected members
seems to be wrong, unless I am misinterpreting things. He says:

"A derived class object may access the protected members of its base
class only through a derived object. The derived class has no special
access to the protected members of base type objects."

He gives the following example:

=========================================================
class Item_base
{
public:
// stuff omitted
protected:
double price;
private:
std::string isbn;

};

class Bulk_item : public Item_base {
// stuff omitted

};

void Bulk_item::memfcn(const Bulk_item&d, const Item_Base& b)
{
// attempt to use protected member
double ret = price; // ok: uses this->price
ret = d.price; // ok: uses price from a Bulk_item object
ret = b.price; // error: no access to price from an Item_base

}

=========================================================

Am I right?

No. The description and the example are both correct.
The point to note is this : "a member function can access all (even
private) members of its arguments of the same type"
In your example:

void Bulk_item::memfcn(const Bulk_item&d, const Item_base& b)
{

double ret = price; // uses this->price

ret = d.price; // The argument d is of type Bulk_item which is
same as type of *this. Hence, all members of d are accessible to every
member function of Bulk_item. Hence d.price works.
(Recollect first part of the sentence from book : A derived class
object may access the protected members of its base class only through
a derived object. Thats other part of reason why d.price works. Note
that d.price would not work if you try to access it from a general
global function like "main")

ret = b.price; // (Recollect second part of sentence from the
book : The derived class has no special access to the protected
members of base type objects. Thats why member 'price' of object b,
which is protected, cannot be accessed by general code.)
}


-Neelesh
 
J

Joe Greer

t said:
Nevermind. I just tried it (which I should have done before
posting). Lippman is correct.

I was confusing:

(1) how a derived class inherits all the members of the base class and
can use the public and protected members, yet cannot use the inherited
private members; in particular, an inherited protected member becomes
a member of the derived class itself;

I think you may be putting too much importance on the whole inheritance thing. Inheritance just
provides access to a different interface to the parent object than just using the object does.

Fundamentally,

class Base {
public:
int a;
protected:
int b;
private:
int c;
};

class A {
private:
Base b;
};

can have the same memory layout as:

class B : private Base {
};

The difference between the two is the interface. (I've chosen private inheritance here so we can ignore
for the moment the inheritance of interface, since that is not where this question seems to lie.) In
the first example, you have access to the public interface of the base class, thus you can only use
'a'. In the second case, you have access to 'a' and 'b'. Neither class A nor class B have access to
'c' which the implementor of Base kept private for class Base's use only.

Where I am going with this is that both class A and class B are users of an interface to class Base.
It's a subtle attitude difference from the idea that inheriting from class Base somehow folds in all of
its members into you, but then removes access to the private members.

and

(2) if a derived class object has access to a base class object (this
doesn't include the base class PART of a derived class object), then
it can only access the base class object's public members and not its
protected or private members.

===

Is this correct? This was a bit too subtle for me to catch at first.

Well the point is that while a Derived object gets a special interface to the Base object from which it
is built. It doesn't, however, get any special rights to any other use of a Base object. So, using
the language from above, you get access to the inherited interface for the Base object if you are
accessing an object your same type, otherwise you get the public interface to the Base object.

If we add another couple classes to the above example:

class C : public Base {
};

class D : public Base {
};

Then we postualate some member functions:

// We only have access to the publics of b because b isn't a 'C'
void C::f(Base &b) {
b.a = 5; //ok, part of Bases publics
b.b = 5; // Bzzzt, Base protected member not available to C
b.c = 5; // Bzzzt, private
}

// We have access to the inherited interface because b is a 'C'
void C:f(C & c) {
c.a = 5; //ok, part of Base's publics, therefore part of C's publics
c.b = 5; // ok, Base protected member of C is available to C
c.c = 5; // Bzzzt, part of Bases privates
}

// We only have the publics because c isn't a 'C' either
void C:f(D & d) {
d.a = 5; //ok
d.b = 5; // Bzzt, Base protected member of D is not available to C
d.c = 5; // Bzzzt, Base private
}

The idea to be conveyed here is that just because class B has a special interface to its class Base,
that doesn't mean it has that same special interface to any other class Base it may encounter.

I see that I have blathered on quite a bit. Hopefully that helps some. In C++ there are often lots of
special cases, but generally they make some sort of sense and hopefully I haven't confused the issue
too much.

joe
 

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,770
Messages
2,569,583
Members
45,074
Latest member
StanleyFra

Latest Threads

Top