首页 文章

私有,公共和受保护继承之间的区别

提问于
浏览
864

C中的 publicprivateprotected 继承有什么区别?我在SO上发现的所有问题都涉及具体案例 .

15 回答

  • 19
    Accessors    | Base Class | Derived Class | World
    —————————————+————————————+———————————————+———————
    public       |      y     |       y       |   y
    —————————————+————————————+———————————————+———————
    protected    |      y     |       y       |   n
    —————————————+————————————+———————————————+———————
    private      |            |               |    
      or         |      y     |       n       |   n
    no accessor  |            |               |
    
    y: accessible
    n: not accessible
    

    基于this java的例子...我觉得一个小 table 值得千言万语:)

  • 4

    如果你从另一个类公开继承,那么每个人都知道你是继承的,任何人都可以通过基类指针多态地使用它 .

    如果你继承受保护,只有你的子类可以多态地使用你 .

    如果你私下继承只有你自己将能够执行父类方法 .

    这基本上象征着其他课程对你与父班关系的了解

  • 7
    Member in base class : Private   Protected   Public
    

    Inheritance typeObject inherited as

    Private            :   Inaccessible   Private     Private   
    Protected          :   Inaccessible   Protected   Protected  
    Public             :   Inaccessible   Protected   Public
    
  • 7

    摘要:

    • 私人:除了课堂以外,没有人能看到它

    • 受保护:私有派生类可以看到它

    • 公众:世界可以看到它

    继承时,您可以(在某些语言中)在某个方向上更改数据成员的保护类型,例如从受保护到公共 .

  • 9

    私人:

    基类的私有成员只能由该基类的成员访问 .

    公众:

    基类的公共成员可以由该基类的成员,其派生类的成员以及基类和派生类之外的成员访问 .

    受保护:

    基类的成员以及其派生类的成员可以访问基类的受保护成员 .


    简而言之:

    private :基地

    protected :基础派生

    public :base派生任何其他成员

  • 50

    这三个关键字也用于完全不同的上下文中以指定 visibility inheritance model .

    此表收集组件声明和继承模型的所有可能组合,在完全定义子类时显示对组件的结果访问 .

    enter image description here

    上面的表格按以下方式解释(请看第一行):

    如果组件声明为public且其类继承为public,则生成的访问权限是公共的 .

    一个例子:

    class Super {
        public:      int p;
        private:     int q;
        protected:   int r;
     };
    
     class Sub : private Super {};
    
     class Subsub : public Sub {};
    

    Subsub 中变量 pqr 的结果访问是 none .

    另一个例子:

    class Super {
        private:     int x;
        protected:   int y;
        public:      int z;
     };
    class Sub : protected Super {};
    

    Sub 中变量 yz 的结果访问是 protected ,变量 x 的访问是 none .

    一个更详细的例子:

    class Super {
    private:
        int storage;
    public:
        void put(int val) { storage = val;  }
        int  get(void)    { return storage; }
    };
    int main(void) {
        Super object;
    
        object.put(100);
        object.put(object.get());
        cout << object.get() << endl;
        return 0;
    }
    

    现在让我们定义一个子类:

    class Sub : Super { };
    
    int main(void) {
        Sub object;
    
        object.put(100);
        object.put(object.get());
        cout << object.get() << endl;
        return 0;
    }
    

    名为Sub的已定义类是 Super 类或 Sub 类的子类,它是从 Super 类派生的 . Sub 类既不引入新变量也不引入新函数 . 这是否意味着 Sub 类的任何对象在 Super 类实际上是 Super 类'对象的副本之后继承了所有特征?

    No . 它没有 .

    如果我们编译以下代码,我们将只得到编译错误,说 putget 方法是不可访问的 . 为什么?

    当我们省略可见性说明符时,编译器会假定我们将应用所谓的 private inheritance . 这意味着所有 public 超类组件都变为 private 访问,私有超类组件根本无法访问 . 因此,它意味着您不允许在子类中使用后者 .

    我们必须告知编译器我们要保留以前使用的访问策略 .

    class Sub : public Super { };
    

    不要被误导:这并不意味着Super类的私有组件(如存储变量)会以某种神奇的方式变成公共组件 . 私人组件将保持私密,公众将继续公开 .

    Sub 类的对象可以与从 Super 类创建的旧兄弟一样"almost" . "Almost"因为作为子类的事实也意味着 class lost access to the private components of the superclass . 我们不能编写 Sub 类的成员函数,它可以直接操作存储变量 .

    这是一个非常严重的限制 . 有没有解决方法?

    Yes .

    第三个访问级别称为 protected . 关键字protected表示标有 behaves like a public one when used by any of the subclasses and looks like a private one to the rest of the world 的组件 . - 这仅适用于公开继承的类(如我们示例中的Super类) -

    class Super {
    protected:
        int storage;
    public:
        void put(int val) { storage = val;  }
        int  get(void)    { return storage; }
    };
    
    class Sub : public Super {
    public:
        void print(void) {cout << "storage = " << storage;}
    };
    
    int main(void) {
        Sub object;
    
        object.put(100);
        object.put(object.get() + 1);
        object.print();
        return 0;
    }
    

    正如您在示例代码中看到的那样,我们为 Sub 类提供了一个新功能,它做了一件重要的事情: it accesses the storage variable from the Super class .

    如果变量被声明为私有,则不可能 . 在主函数范围内,变量仍然是隐藏的,所以如果你写的东西如下:

    object.storage = 0;
    

    编译器会通知您它是 error: 'int Super::storage' is protected .

    最后,最后一个程序将产生以下输出:

    storage = 101
    
  • 1278

    公共继承模拟IS-A关系 . 同

    class B {};
    class D : public B {};
    

    D 都是 B .

    私有继承模拟IS-IMPLEMENTED-USING关系(或任何被称为的关系) . 同

    class B {};
    class D : private B {};
    

    D 不是 B ,但每个 D 在其实现中使用 B . 可以通过使用包含来消除私有继承:

    class B {};
    class D {
      private: 
        B b_;
    };
    

    这个 D 也可以使用 B 来实现,在这种情况下使用 b_ . 包含是类型之间不那么紧密的耦合而不是继承,所以通常它应该是首选 . 有时使用包含而不是私有继承不是私人继承方便 . 这通常是懒惰的蹩脚借口 .

    我认为没有人知道 protected 继承模型是什么 . 至少我还没有看到任何令人信服的解释 .

  • 6
    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
    };
    

    重要说明:B,C和D类都包含变量x,y和z . 这只是访问问题 .

    关于受保护和私有继承的使用,您可以阅读here .

  • 34

    限制继承的可见性将使代码无法看到某些类继承另一个类:从派生到基类的隐式转换将不起作用,并且从基础到派生的 static_cast 也将不起作用 .

    只有类的成员/朋友才能看到私有继承,只有成员/朋友和派生类才能看到受保护的继承 .

    public 继承

    • IS-A继承 . 按钮是一个窗口,在需要窗口的任何地方,也可以传递按钮 .
    class button : public window { };
    

    protected 继承

    • 受保护的实施条款 . 很少有用 . 在 boost::compressed_pair 中使用从空类派生并使用空基类优化来保存内存(下面的示例不使用模板来保持点):
    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 继承

    • 实施条款 . 基类的用法仅用于实现派生类 . 对traits有用,如果size很重要(只包含函数的空特性将使用空基类优化) . 但是,通常遏制是更好的解决方案 . 字符串的大小是至关重要的,因此这是一个常见的用法
    template<typename StorageModel>
    struct string : private StorageModel {
    public:
      void realloc() {
        // uses inherited function
        StorageModel::realloc();
      }
    };
    

    public 成员

    • 聚合
    class pair {
    public:
      First first;
      Second second;
    };
    
    • 存取器
    class window {
    public:
        int getWidth() const;
    };
    

    protected 成员

    • 为派生类提供增强的访问权限
    class stack {
    protected:
      vector<element> c;
    };
    
    class window {
    protected:
      void registerClass(window_descriptor w);
    };
    

    private 成员

    • 保持实施细节
    class window {
    private:
      int width;
    };
    

    请注意,C样式转换有意允许以定义和安全的方式将派生类转换为受保护的或私有的基类,并且也可以转换到另一个方向 . 应该不惜一切代价避免这种情况,因为它可以使代码依赖于实现细节 - 但如果有必要,您可以使用这种技术 .

  • 23

    1) Public Inheritance

    一个 . Derived类中无法访问Base类的私有成员 .

    湾Base类的受保护成员在Derived类中保持受保护 .

    C . Base类的公共成员在Derived类中保持公共状态 .

    因此,其他类可以通过Derived类对象使用Base类的公共成员 .

    2) Protected Inheritance

    一个 . Derived类中无法访问Base类的私有成员 .

    湾Base类的受保护成员在Derived类中保持受保护 .

    C . Base类的公共成员也成为Derived类的受保护成员 .

    因此,其他类不能通过Derived类对象使用Base类的公共成员;但它们可用于Derived的子类 .

    3) Private Inheritance

    一个 . Derived类中无法访问Base类的私有成员 .

    湾Base类的受保护和公共成员成为Derived类的私有成员 .

    因此,其他类不能通过Derived类对象访问Base类的成员,因为它们在Derived类中是私有的 . 因此,即使Derived类的子类也无法访问它们 .

  • 101

    它与如何从派生类公开基类的公共成员有关 .

    • public - >基类的公共成员将是公共的(通常是默认的)

    • protected - >基类的公共成员将受到保护

    • private - >基类的公共成员将是私有的

    正如litb指出的那样,公共继承是传统的继承,你会在大多数编程语言中看到 . 那就是它 Build 了一种关系 . 私有继承,是C所特有的AFAIK,是一种关系 . 那就是你想在派生类中使用 use 公共接口,但是要't want the user of the derived class to have access to that interface. Many argue that in this case you should aggregate the base class, that is instead of having the base class as a private base, make in a member of derived in order to reuse base class'的功能 .

  • 3

    受保护的数据成员可以从您的类继承的任何类访问 . 但是,私人数据成员不能 . 假设我们有以下内容:

    class MyClass {
        private:
            int myPrivateMember;    // lol
        protected:
            int myProtectedMember;
    };
    

    从您的扩展程序到此类,引用 this.myPrivateMember 将不起作用 . 但是, this.myProtectedMember 会 . 该值仍然是封装的,因此如果我们有一个名为 myObj 的类的实例化,那么 myObj.myProtectedMember 将不起作用,因此它在功能上类似于私有数据成员 .

  • 12

    我找到了一个简单的答案,所以想过将它发布给我以后的参考 .

    它的来自链接http://www.learncpp.com/cpp-tutorial/115-inheritance-and-access-specifiers/

    class Base
    {
    public:
        int m_nPublic; // can be accessed by anybody
    private:
        int m_nPrivate; // can only be accessed by Base member functions (but not derived classes)
    protected:
        int m_nProtected; // can be accessed by Base member functions, or derived classes.
    };
    
    class Derived: public Base
    {
    public:
        Derived()
        {
            // Derived's access to Base members is not influenced by the type of inheritance used,
            // so the following is always true:
    
            m_nPublic = 1; // allowed: can access public base members from derived class
            m_nPrivate = 2; // not allowed: can not access private base members from derived class
            m_nProtected = 3; // allowed: can access protected base members from derived class
        }
    };
    
    int main()
    {
        Base cBase;
        cBase.m_nPublic = 1; // allowed: can access public members from outside class
        cBase.m_nPrivate = 2; // not allowed: can not access private members from outside class
        cBase.m_nProtected = 3; // not allowed: can not access protected members from outside class
    }
    
  • 61

    它本质上是派生类中基类的公共成员和受保护成员的访问保护 . 通过公共继承,派生类可以查看基类的公共成员和受保护成员 . 有了私有继承,它不能 . 使用protected,派生类和从中派生的任何类都可以看到它们 .

  • 934

    要回答这个问题,我想先用自己的话来描述成员的访问者 . 如果您已经知道这一点,请跳至 Headers “next:” .

    我知道有三种访问器: publicprotectedprivate .

    让:

    class Base {
        public:
            int publicMember;
        protected:
            int protectedMember;
        private:
            int privateMember;
    };
    
    • 所有知道 Base 的东西也知道 Base 包含 publicMember .

    • 只有孩子(及其子女)知道 Base 包含 protectedMember .

    • 没有人,但 Base 知道 privateMember .

    通过“意识到”,我的意思是“承认存在,从而能够访问” .

    下一个:

    公共,私有和受保护的继承也是如此 . 让我们考虑一个类 Base 和一个继承自 Base 的类 Child .

    • 如果继承是 public ,那么知道 BaseChild 的所有内容也都知道 ChildBase 继承 .

    • 如果继承是 protected ,则只有 Child 及其子项知道它们是从 Base 继承的 .

    • 如果继承是 private ,则 Child 以外的任何人都不知道继承 .

相关问题