tags:

views:

161

answers:

4

I was going over some sample questions for an upcoming test, and this question is totally confusing me. Any help would be appreciated.

Consider the following code:

class GraduateStudent : public Student 
{
  ...
};

If the word "public" is omitted, GraduateStudent uses private inheritance, which means which of the following?

  1. GraduateStudent objects may not use methods of Student.

  2. GraduateStudent does not have access to private objects of Student.

  3. No method of GraduateStudent may call a method of Student.

  4. Only const methods of GraduateStudent can call methods of Student.

+22  A: 

Although this is a bare homework-ish question, I'm going to answer it because it is a terrible question. I would almost consider it a trick question, and it doesn't really make for a good test of knowledge.

The answer is 2. GraduateStudent does not have access to private objects of Student., except that this has nothing at all to do with private inheritance. Point 2 would be true whether or not the public keyword were present, since derived classes never have access to the private members of their base classes, no matter how they inherit.

Private inheritance means essentially two things (as opposed to public inheritance):

  1. All public methods of Student become private methods in GraduateStudent. That means that if, for example, Student has a public method foo(), then GraduateStudent has a private method foo().

  2. The base class is "inaccessible", which means that polymorphism does not work. In layman's terms, this means that if GraduateStudent inherits privately from Student, then you cannot treat a GraduateStudent* as if it were a Student* (or a GraduateStudent& as if it were a Student&).

It's possible that the author of the question also meant for point 1 to be a correct answer, but it is ambiguously worded. What does it mean that "GraduateStudent objects may not use methods of Student"? It's possible that the intent is for this to mean that you cannot call methods inherited from Student on objects of type GraduateStudent, like I wrote in the first point above, but the GraduateStudent object itself, within its methods, can use methods of Student.

For example:

class Student {
  public: 
    void foo() {};
};

class GraduateStudent : Student {
  public: 
   void bar()
   {
     foo(); // Legal
   }
};

int main() {
  GraduateStudent g;

  g.bar(); // Legal
  g.foo(); // Illegal

  return 0;
};
Tyler McHenry
Right - it makes me wonder if the author of the question meant for (1) to be the correct answer but just worded it awfully.
sechastain
Well, either way (2) is definitely true, even if redundant, so the answer is either (2) or (1) and (2).
Tyler McHenry
You say "derived classes never have access to the private members of their base classes, no matter how they inherit.". If the inheritance is public, and all methods are public in the dervied class. Why, then, can't they be accessed by obects of the derived class?
xbonez
+1 for the effort and the clarification of a badly worded homework question ...
neuro
@xbones Not sure I'm following you. If `Student` has a *private* method `doPrivateStuff()` or a private member `m_myPrivateData`, then `GraduateStudent` cannot access them even if it inherits publicly. That's what private means. The access level of inheritance specifies which level of access the *public* methods and members of the base class will have in the derived class. With public inheritance, things that are public in the base stay public in the derived. With private inheritance, things that are public in the base become private in the derived.
Tyler McHenry
There is also, by the same token, protected inheritance where things that are public in the base become protected in the derived.
Tyler McHenry
+1 for taking the time to write this explanation. Having read it and reread the original question, I think Option 1 was probably meant to read "code that uses GraduateStudent objects may not use methods of Student (except where the code is a method of GraduateStudent)."
JeremyP
Actually, the access level specified for inheritance may also influence the access level of `protected` methods that are inherited. If `Student` had a protected method `foo()`, then an object deriving from `GraduateStudent` would not be able to call it.
Matthieu M.
+3  A: 

The only correct answer that I see is 2, but that does not depend on whether GraduateStudent inherits from Student privately or publicly.

Private inheritance means that it is private knowledge that GraduateStudent is a Student, so only friends of GraduateStudent and GraduateStudent members can static_cast GraduateStudent& to Student& and GraduateStudent* to Student*, access public or protected member variables of Student, and call public or protected member functions of Student.

See: http://www.parashift.com/c++-faq-lite/private-inheritance.html

Daniel Trebbien
+2  A: 
1. GraduateStudent objects may not use methods of Student.

Not true, all GraduateStudent objects can use any public or protected members of Students (obviously private members are the exception here) internally. Also any outsider using these objects cannot access the base Student class of the object, the access to the base class must happen within the context of the GraduateStudent methods.

2. GraduateStudent does not have access to private objects of Student.

Yes

3. No method of GraduateStudent may call a method of Student.

Not true

4. Only const methods of GraduateStudent can call methods of Student.

Nope, there's no distinction made on const members having more access to the base class than non-const members would have.

toby
A: 

First: the inheritance access specifier does not modify the way Derived interacts with Base, it modifies the way the world can treat a Derived object as if it were a Base.

Consider:

struct A{};
struct B: xxxx A
{
  friend void friendly();
};
struct C: B {};

void outsider();

A very simple table: I summarize which zones of A can be accessed by the various actors.

xxxx         public      protected      private

B            pub/prot    pub/prot       pub/prot

friendly     pub/prot    pub/prot       pub/prot    *

C            pub/prot    pub/prot       --

outsider     pub         --             --

Note (*): A friend has the same rights that the object itself, no surprise there.

A simple rule of thumb is to consider that the inheritance access specifier overrides the access specifiers of the base class if they are looser.

Since nothing is looser than public, it does not change anything. protected means that the public section of the Base becomes protected, and private means that the public and protected sections become private.

Matthieu M.