Access to members defined within a derived class is controlled in exactly the same way as access is handled for any other class (Section 12.1.2, p. 432). A derived class may define zero or more access labels that specify the access level of the members following that label. Access to the members the class inherits is controlled by a combination of the access level of the member in the base class and the access label used in the derived class' derivation list.
Note:Each class controls access to the members it defines. A derived class may further restrict but may not loosen the access to the members that it inherits.
In public inheritance , the members of the base retain their access levels: The publicmembers of the base are public members of the derived and the protected members of the base are protectedin the derived.
In protected inheritance , the public and protected members of the base class are protected members in the derived class.
In private inheritance , all the members of the base class are private in the derived class.
Interface versus Implementation Inheritance
A publicly derived class inherits the interface of its base class; it has the same interface as its base class. In well-designed class hierarchies, objects of a publicly derived class can be used wherever an object of the base class is expected.
Classes derived using either privateor protecteddo not inherit the base-class interface. Instead, these derivations are often referred to as implementation inheritance. The derived class uses the inherited class in its implementation but does not expose the fact of the inheritance as part of its interface.
Key Concept: Inheritance versus Composition
When we define one class as publicly inherited from another, the derived class should reflect a so-called "Is A" relationship to the base class. In our bookstore example, our base class represents the concept of a book sold at a stipulated price. Our Bulk_itemis a kind of book, but one with a different pricing strategy.
Another common relationship among types is a so-called "Has A" relationship. Our bookstore classes have a price and they have an ISBN. Types related by a "Has A" relationship imply membership. Thus, our bookstore classes are composed from members representing the price and the ISBN.
In this hierarchy, sizeis publicin Basebut privatein Derived. To make size publicin Derivedwe can
add a usingdeclaration for it to a publicsection in Derived.By changing the definition of Derivedasfollows, we can make the size member accessible to users and n accessible to classes subsequently derived from Derived:
class Derived : private Base {
public:
// maintain access levels for members related to the size of the object
using Base::size;
protected:
using Base::n;
// ...
};
The form is the same except that the left-hand side of the scope operator is a class name instead of a namespace name.
Default Inheritance Protection Levels
class Base { /* ... */ };
struct D1 : Base { /* ... */ }; // public inheritance by default
class D2 : Base { /* ... */ }; // private inheritance by default
Best Practices: Although private inheritance is the default when using the class keyword, it is also relatively rare in practice. Because private inheritance is so rare, it is usually a good idea to explicitly specify private, rather than rely on the default. Being explicit makes it clear that private inheritance is intended and not an oversight.