Difference between private, public, and protected inheritance

What is the difference between public , private , and protected inheritance in C++? All of the questions I've found on SO deal with specific cases.


To answer that question, I'd like to describe member's accessors first in my own words. If you already know this, skip to the heading "next:".

There are three accessors that I'm aware of: public , protected and private .

Let:

class Base {
    public:
        int publicMember;
    protected:
        int protectedMember;
    private:
        int privateMember;
};
  • Everything that is aware of Base is also aware that Base contains publicMember .
  • Only the children (and their children) are aware that Base contains protectedMember .
  • No one but Base is aware of privateMember .
  • By "is aware of", I mean "acknowledge the existence of, and thus be able to access".

    next:

    The same happens with public, private and protected inheritance. Let's consider a class Base and a class Child that inherits from Base .

  • If the inheritance is public , everything that is aware of Base and Child is also aware that Child inherits from Base .
  • If the inheritance is protected , only Child , and its children, are aware that they inherit from Base .
  • If the inheritance is private , no one other than Child is aware of the inheritance.

  • class A 
    {
    public:
        int x;
    protected:
        int y;
    private:
        int z;
    };
    
    class B : public A
    {
        // x is public
        // y is protected
        // z is not accessible from B
    };
    
    class C : protected A
    {
        // x is protected
        // y is protected
        // z is not accessible from C
    };
    
    class D : private A    // 'private' is default for classes
    {
        // x is private
        // y is private
        // z is not accessible from D
    };
    

    IMPORTANT NOTE: Classes B, C and D all contain the variables x, y and z. It is just question of access.

    About usage of protected and private inheritance you could read here.


    Limiting the visibility of inheritance will make code not able to see that some class inherits another class: Implicit conversions from the derived to the base won't work, and static_cast from the base to the derived won't work either.

    Only members/friends of a class can see private inheritance, and only members/friends and derived classes can see protected inheritance.

    public inheritance

  • IS-A inheritance. A button is-a window, and anywhere where a window is needed, a button can be passed too.

    class button : public window { };
    
  • protected inheritance

  • Protected implemented-in-terms-of. Rarely useful. Used in boost::compressed_pair to derive from empty classes and save memory using empty base class optimization (example below doesn't use template to keep being at the point):

    struct empty_pair_impl : protected empty_class_1 
    { non_empty_class_2 second; };
    
    struct pair : private empty_pair_impl {
      non_empty_class_2 &second() {
        return this->second;
      }
    
      empty_class_1 &first() {
        return *this; // notice we return *this!
      }
    };
    
  • private inheritance

  • Implemented-in-terms-of. The usage of the base class is only for implementing the derived class. Useful with traits and if size matters (empty traits that only contain functions will make use of the empty base class optimization). Often containment is the better solution, though. The size for strings is critical, so it's an often seen usage here

    template<typename StorageModel>
    struct string : private StorageModel {
    public:
      void realloc() {
        // uses inherited function
        StorageModel::realloc();
      }
    };
    

  • public member

  • Aggregate

    class pair {
    public:
      First first;
      Second second;
    };
    
  • Accessors

    class window {
    public:
        int getWidth() const;
    };
    
  • protected member

  • Providing enhanced access for derived classes

    class stack {
    protected:
      vector<element> c;
    };
    
    class window {
    protected:
      void registerClass(window_descriptor w);
    };
    
  • private member

  • Keep implementation details

    class window {
    private:
      int width;
    };
    

  • Note that C-style casts purposely allows casting a derived class to a protected or private base class in a defined and safe manner and to cast into the other direction too. This should be avoided at all costs, because it can make code dependent on implementation details - but if necessary, you can make use of this technique.

    链接地址: http://www.djcxy.com/p/2216.html

    上一篇: float和double有什么区别?

    下一篇: 私人,公共和受保护继承的区别