公共继承、私有继承和受保护继承之间有什么区别?

发布于 2024-07-20 06:25:34 字数 88 浏览 6 评论 0原文

C++ 中的 publicprivateprotected 继承有什么区别?

What is the difference between public, private, and protected inheritance in C++?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(17

夏天碎花小短裙 2024-07-27 06:25:35

公共继承对 IS-A 关系进行建模。 每个

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

D都是一个B

私有继承对 IS-IMPLMENTED-USING 关系(或任何所谓的关系)进行建模。 对于

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

D 来说,不是 B,但是每个 D 都使用它的 B其实施。 私有继承总是可以通过使用包含来消除:

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

这个D也可以使用B来实现,在本例中使用它的b_。 与继承相比,包含是类型之间的一种不太紧密的耦合,因此通常应该首选它。 有时使用包含而不是私有继承不如私有继承方便。 这通常是懒惰的蹩脚借口。

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

Public inheritance models an IS-A relationship. With

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

every D is a B.

Private inheritance models an IS-IMPLEMENTED-USING relationship (or whatever that's called). With

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

a D is not a B, but every D uses its B in its implementation. Private inheritance can always be eliminated by using containment instead:

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

This D, too, can be implemented using B, in this case using its b_. Containment is a less tight coupling between types than inheritance, so in general it should be preferred. Sometimes using containment instead of private inheritance is not as convenient as private inheritance. Often that's a lame excuse for being lazy.

I don't think anyone knows what protected inheritance models. At least I haven't seen any convincing explanation yet.

微凉 2024-07-27 06:25:35
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 示例...我认为一张小表值一千字:)

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

Based on this example for java... I think a little table worth a thousand words :)

风和你 2024-07-27 06:25:35

如果您从另一个类公开继承,那么每个人都知道您正在继承,并且任何人都可以通过基类指针以多态方式使用您。

如果您受保护地继承,则只有您的子类才能以多态方式使用您。

如果您私有继承,则只有您自己才能执行父类方法。

这基本上象征着其他班级对您与父班级的关系的了解

If you inherit publicly from another class, everybody knows you are inheriting and you can be used polymorphically by anyone through a base class pointer.

If you inherit protectedly only your children classes will be able to use you polymorphically.

If you inherit privately only yourself will be able to execute parent class methods.

Which basically symbolizes the knowledge the rest of the classes have about your relationship with your parent class

梅倚清风 2024-07-27 06:25:35

受保护的数据成员可以由从您的类继承的任何类访问。 然而,私有数据成员则不能。 假设我们有以下内容:

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

在此类的扩展中,引用 this.myPrivateMember 将不起作用。 但是,this.myProtectedMember 会。 该值仍然是封装的,因此如果我们有一个名为 myObj 的此类实例化,则 myObj.myProtectedMember 将无法工作,因此它在功能上类似于 private数据成员。

Protected data members can be accessed by any classes that inherit from your class. Private data members, however, cannot. Let's say we have the following:

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

From within your extension to this class, referencing this.myPrivateMember won't work. However, this.myProtectedMember will. The value is still encapsulated, so if we have an instantiation of this class called myObj, then myObj.myProtectedMember won't work, so it is similar in function to a private data member.

相守太难 2024-07-27 06:25:35

我尝试使用下图解释继承。

主要要点是父类的私有成员永远不能从派生/子类直接访问,但您可以使用父类的成员函数来访问父类的私有成员。
私有变量始终存在于派生类中,但不能被派生类访问。 就像他们的,但你无法亲眼看到,但如果你问家长班的人,他可以向你描述。
继承映射 cpp

I have tried explaining inheritance using a picture below.

The main gist is that the private members of parent class are never directly accessible from derived/child class but you can use parent class's member function to access the private members of parent class.
Private variables are always present in derived class but it cannot be accessed by derived class. Its like its their but you cannot see with your own eyes but if you ask someone form the parent class then he can describe it to you.
Inheritance Mapping cpp

止于盛夏 2024-07-27 06:25:35

摘要:

  • Private:除了类内部,没有人可以看到它
  • Protected:私有+派生类都可以看到它
  • Public:全世界都可以看到它

继承时,你可以(在某些语言中)在某些情况下更改数据成员的保护类型方向,例如从受保护到公共。

Summary:

  • Private: no one can see it except for within the class
  • Protected: Private + derived classes can see it
  • Public: the world can see it

When inheriting, you can (in some languages) change the protection type of a data member in certain direction, e.g. from protected to public.

萧瑟寒风 2024-07-27 06:25:35

Private:

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

公共:

基类的公共成员可以被该基类的成员、其派生类的成员以及基类和派生类之外的成员访问。

受保护:

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


简而言之:

私有:基础

受保护:基础+派生

公共:基础+派生+任何其他成员

Private:

The private members of a base class can only be accessed by members of that base class .

Public:

The public members of a base class can be accessed by members of that base class, members of its derived class as well as the members which are outside the base class and derived class.

Protected:

The protected members of a base class can be accessed by members of base class as well as members of its derived class.


In short:

private: base

protected: base + derived

public: base + derived + any other member

小霸王臭丫头 2024-07-27 06:25:35

它本质上是对派生类中基类的 public 和 protected 成员的访问保护。 通过公共继承,派生类可以看到基类的公共成员和受保护成员。 对于私有继承,则不能。 通过 protected,派生类以及从该类派生的任何类都可以看到它们。

It's essentially the access protection of the public and protected members of the base class in the derived class. With public inheritance, the derived class can see public and protected members of the base. With private inheritance, it can't. With protected, the derived class and any classes derived from that can see them.

夕色琉璃 2024-07-27 06:25:35

我找到了一个简单的答案,因此也想将其发布以供将来参考。 它来自链接 https://www.learncpp.com /cpp-tutorial/115-inheritance-and-access-specifiers/

类基础 
  { 
  民众: 
      int m_nPublic;   // 任何人都可以访问 
  私人的: 
      int m_nPrivate;   // 只能被基类成员函数访问(不能被派生类访问) 
  受保护: 
      int m_nProtected;   // 可以由基类成员函数或派生类访问。 
  }; 
 
  派生类:public Base 
  { 
  民众: 
      衍生的() 
      { 
          // Derived 对 Base 成员的访问不受所使用的继承类型的影响, 
          // 因此以下内容始终为真: 
 
          m_n公共 = 1;   // 允许:可以从派生类访问公共基成员 
          m_nPrivate = 2;   // 不允许:无法从派生类访问私有基成员 
          m_n受保护= 3;   // 允许:可以从派生类访问受保护的基成员 
      } 
  }; 
 
  int main() 
  { 
      基础cBase; 
      cBase.m_nPublic = 1;   // allowed: 可以从外部类访问公共成员 
      cBase.m_nPrivate = 2;   // 不允许:不能从外部类访问私有成员 
      cBase.m_nProtected = 3;   // 不允许:不能从外部类访问受保护的成员 
  } 
  

I found an easy answer and so thought of posting it for my future reference too. It's from the link https://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
}
傲影 2024-07-27 06:25:35

继承

  • public:无任何内容,与基类
  • protected相同:Public -> 受保护,否则相同。
  • 私有(默认):公开和公开 受保护-> 私有(现在一切都是私有的!)

区分类对象从外部和内部的外观非常重要。

从类内部:您可以从基类访问非私有的所有字段和方法。 继承的类型在这里并不重要。

从外部:您只能访问公共类中的方法和字段。 这意味着基类的接口必须是公共的,并且也必须由派生类公开继承,以便可以跨域携带访问属性。

受保护怎么样?

保护基本上意味着:不能从外部获得,但可以从内部获得。

这里有一些演示代码它。 所有评论的内容都不会编译:

#include <iostream>

struct base {
private:
    int a;
    auto get_a() {return a; }
protected:
    int b;
    auto get_b() {return b; }
public:
    int c;
    auto get_c() {return c; }
};

struct derive_private : private base {
    /* From inside */
    auto print() {
        // a = 3;
        b = 2;
        c = 3;
        // std::cout << get_a() << std::endl;
        std::cout << get_b() << std::endl;
        std::cout << get_c() << std::endl;
    }
};

struct derive_protected : protected base {
    /* From inside */
    auto print() {
        // a = 3;
        b = 14;
        c = 35;
        // std::cout << get_a() << std::endl;
        std::cout << get_b() << std::endl;
        std::cout << get_c() << std::endl;
    }
};

struct derive_public : public base {
    /* From inside */
    auto print() {
        // a = 3;
        b = 14;
        c = 35;
        // std::cout << get_a() << std::endl;
        std::cout << get_b() << std::endl;
        std::cout << get_c() << std::endl;
    }
};

int main() {
    /* From outside */

    derive_private mypriv;
    mypriv.print();
    // mypriv.a = 2;
    // mypriv.b = 5;
    // mypriv.c = 29;
    // std::cout << mypriv.get_a() << std::endl;
    // std::cout << mypriv.get_b() << std::endl;
    // std::cout << mypriv.get_c() << std::endl;

    derive_protected myprot;
    myprot.print();
    // myprot.a = 17;
    // myprot.b = 8;
    // myprot.c = 31;
    // std::cout << myprot.get_a() << std::endl;
    // std::cout << myprot.get_b() << std::endl;
    // std::cout << myprot.get_c() << std::endl;

    derive_public mypub;
    mypub.print();
    // mypub.a = 91;
    // mypub.b = 101;
    mypub.c = 205;
    // std::cout << mypub.get_a() << std::endl;
    // std::cout << mypub.get_b() << std::endl;
    std::cout << mypub.get_c() << std::endl;
}

Inheritance

  • public: nothing, same as base class
  • protected: Public -> protected, otherwise same.
  • private (default): Public & protected -> private (everything is now private!)

It's then important to differentiate how a class object looks from the outside vs from the inside.

From inside class: You can access all fields and methods from base that are not private. The kind of inheritance doesn't matter here.

From outside: You can only access methods and fields from class that are public. This means the interface of the base needs to be public and also publicly inherited by derived so that the access propertiers are carried accross.

What about protected?

Protected basically means: Not available from outside, but from inside.

Here's some code to demonstrate it. Everything commented will not compile:

#include <iostream>

struct base {
private:
    int a;
    auto get_a() {return a; }
protected:
    int b;
    auto get_b() {return b; }
public:
    int c;
    auto get_c() {return c; }
};

struct derive_private : private base {
    /* From inside */
    auto print() {
        // a = 3;
        b = 2;
        c = 3;
        // std::cout << get_a() << std::endl;
        std::cout << get_b() << std::endl;
        std::cout << get_c() << std::endl;
    }
};

struct derive_protected : protected base {
    /* From inside */
    auto print() {
        // a = 3;
        b = 14;
        c = 35;
        // std::cout << get_a() << std::endl;
        std::cout << get_b() << std::endl;
        std::cout << get_c() << std::endl;
    }
};

struct derive_public : public base {
    /* From inside */
    auto print() {
        // a = 3;
        b = 14;
        c = 35;
        // std::cout << get_a() << std::endl;
        std::cout << get_b() << std::endl;
        std::cout << get_c() << std::endl;
    }
};

int main() {
    /* From outside */

    derive_private mypriv;
    mypriv.print();
    // mypriv.a = 2;
    // mypriv.b = 5;
    // mypriv.c = 29;
    // std::cout << mypriv.get_a() << std::endl;
    // std::cout << mypriv.get_b() << std::endl;
    // std::cout << mypriv.get_c() << std::endl;

    derive_protected myprot;
    myprot.print();
    // myprot.a = 17;
    // myprot.b = 8;
    // myprot.c = 31;
    // std::cout << myprot.get_a() << std::endl;
    // std::cout << myprot.get_b() << std::endl;
    // std::cout << myprot.get_c() << std::endl;

    derive_public mypub;
    mypub.print();
    // mypub.a = 91;
    // mypub.b = 101;
    mypub.c = 205;
    // std::cout << mypub.get_a() << std::endl;
    // std::cout << mypub.get_b() << std::endl;
    std::cout << mypub.get_c() << std::endl;
}
别在捏我脸啦 2024-07-27 06:25:34
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。 这只是访问的问题。

关于受保护继承和私有继承的使用,您可以在此处阅读。

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.

云之铃。 2024-07-27 06:25:34

为了回答这个问题,我想首先用我自己的话来描述成员的访问器。 如果您已经知道这一点,请跳至标题“下一步:”。

我知道三种访问器:publicprotectedprivate

让:

class Base {
    public:
        int publicMember;
    protected:
        int protectedMember;
    private:
        int privateMember;
};
  • 所有知道 Base 的东西也都知道 Base 包含 publicMember
  • 只有孩子(及其孩子)知道 Base 包含 protectedMember
  • 除了 Base 之外,没有人知道 privateMember

我所说的“意识到”是指“承认其存在,从而能够访问”。

下一页:

同样的情况也发生在公共、私有和受保护的继承上。 让我们考虑一个类 Base 和一个继承自 Base 的类 Child

  • 如果继承是public,则所有知道BaseChild的东西也会知道Child继承自<代码>基础。
  • 如果继承受保护,则只有Child 及其子级知道它们是从Base 继承的。
  • 如果继承是private,则除了Child 之外,没有人知道该继承。

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.
带刺的爱情 2024-07-27 06:25:34

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

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

公共继承

  1. IS-A继承。 按钮就是一个窗口,任何需要窗口的地方都可以传递按钮。

    类按钮:公共窗口 { }; 
      

受保护继承

  1. 受保护的实现方式。 很少有用。 在 boost::compressed_pa​​ir 中使用,从空类派生并使用空基类优化节省内存(下面的示例不使用模板来保持当前状态):

    structempty_pair_impl:受保护的empty_class_1  
      { non_empty_class_2 第二;   }; 
    
      结构对:私有empty_pair_impl { 
        non_empty_class_2 &second() { 
          返回此->第二个; 
        } 
    
        空_class_1 &first() { 
          返回*这个;   // 注意我们返回*this! 
        } 
      }; 
      

private继承

  1. 实现的。 基类的用法仅用于实现派生类。 对于特征很有用,如果大小很重要(仅包含函数的空特征将利用空基类优化)。 不过,遏制通常是更好的解决方案。 字符串的大小至关重要,因此这里经常看到它的用法

    模板 
      结构字符串:私有存储模型{ 
      民众: 
        无效重新分配(){ 
          // 使用继承的函数 
          存储模型::realloc(); 
        } 
      }; 
      

public member

  1. Aggregate

    类对 { 
      民众: 
        第一第一; 
        第二第二; 
      }; 
      
  2. 访问器

    类窗口 { 
      民众: 
          int getWidth() const; 
      }; 
      

受保护成员

  1. 为派生类提供增强的访问

    类堆栈{ 
      受保护: 
        向量<元素>   C; 
      }; 
    
      类窗口{ 
      受保护: 
        void registerClass(window_descriptor w); 
      }; 
      

私有成员

  1. 提供增强的访问

    保留实现细节

    类窗口 { 
      私人的: 
        整数宽度; 
      }; 
      

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

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

  1. 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

  1. 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

  1. 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

  1. Aggregate

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

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

protected member

  1. Providing enhanced access for derived classes

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

private member

  1. 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.

贩梦商人 2024-07-27 06:25:34

这三个关键字还用在完全不同的上下文中来指定可见性继承模型

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

在此处输入图像描述

上表的解释如下(看第一行):

如果一个组件声明public,并且其类继承public,则结果访问公开

示例:

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

 class Sub : private Super {};

 class Subsub : public Sub {};

变量 pqr< 的访问权限Subsub 类中的 /code> 为 none

另一个例子:

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

Sub 类中变量 yz 的访问结果是受保护,而变量 x

更详细的示例:

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 类对象的副本之后的所有特征?

。 事实并非如此。

如果我们编译以下代码,我们只会得到编译错误,指出 putget 方法无法访问。 为什么?

当我们省略可见性说明符时,编译器假设我们将应用所谓的私有继承。 这意味着所有公共超类组件都会变成私有访问,私有超类组件将根本无法访问。 因此,这意味着您不允许在子类中使用后者。

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

class Sub : public Super { };

不要被误导:这并不意味着 Super 的私有组件
类(如存储变量)将变成公共类
有点神奇的方式。 私有组件将保持私有公共
将保持公开

Sub 类的对象可能会与从 Super 类创建的较早的同级对象执行“几乎”相同的操作。 “几乎”因为作为子类这一事实也意味着类失去了对超类的私有组件的访问。 我们无法编写 Sub 类的成员函数来直接操作存储变量。

这是一个非常严格的限制。 有什么解决方法吗?

第三个访问级别称为受保护。 关键字 protected 意味着用它标记的组件在被任何子类使用时表现得像公共组件,而对于世界其他地方看起来像私有组件。 -- 这只适用于公共继承的类(例如我们示例中的 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 提供了新功能类,它做了一件重要的事情:它从超级类访问存储变量

如果变量被声明为私有的,这是不可能的。
在主函数作用域中,变量仍然是隐藏的,因此如果您编写类似以下内容:

object.storage = 0;

编译器将通知您这是一个错误:'int Super::storage' is protected

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

storage = 101

These three keywords are also used in a completely different context to specify the visibility inheritance model.

This table gathers all of the possible combinations of the component declaration and inheritance model presenting the resulting access to the components when the subclass is completely defined.

enter image description here

The table above is interpreted in the following way (take a look at the first row):

if a component is declared as public and its class is inherited as public the resulting access is public.

An example:

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

 class Sub : private Super {};

 class Subsub : public Sub {};

The resulting access for variables p, q, r in class Subsub is none.

Another example:

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

The resulting access for variables y, z in class Sub is protected and for variable x is none.

A more detailed example:

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

Now lets define a subclass:

class Sub : Super { };

int main(void) {
    Sub object;

    object.put(100);
    object.put(object.get());
    cout << object.get() << endl;
    return 0;
}

The defined class named Sub which is a subclass of class named Super or that Sub class is derived from the Super class.
The Sub class introduces neither new variables nor new functions. Does it mean that any object of the Sub class inherits all the traits after the Super class being in fact a copy of a Super class’ objects?

No. It doesn’t.

If we compile the following code, we will get nothing but compilation errors saying that put and get methods are inaccessible. Why?

When we omit the visibility specifier, the compiler assumes that we are going to apply the so-called private inheritance. It means that all public superclass components turn into private access, private superclass components won't be accessible at all. It consequently means that you are not allowed to use the latter inside the subclass.

We have to inform the compiler that we want to preserve the previously used access policy.

class Sub : public Super { };

Don’t be misled: it doesn’t mean that private components of the Super
class (like the storage variable) will turn into public ones in a
somewhat magical way. Private components will remain private, public
will remain public.

Objects of the Sub class may do "almost" the same things as their older siblings created from the Super class. "Almost" because the fact of being a subclass also means that the class lost access to the private components of the superclass. We cannot write a member function of the Sub class which would be able to directly manipulate the storage variable.

This is a very serious restriction. Is there any workaround?

Yes.

The third access level is called protected. The keyword protected means that the component marked with it behaves like a public one when used by any of the subclasses and looks like a private one to the rest of the world. -- This is true only for the publicly inherited classes (like the Super class in our example) --

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

As you see in the example code we a new functionality to the Sub class and it does one important thing: it accesses the storage variable from the Super class.

It wouldn’t be possible if the variable was declared as private.
In the main function scope the variable remains hidden anyway so if you write anything like:

object.storage = 0;

The compiler will inform you that it is an error: 'int Super::storage' is protected.

Finally, the last program will produce the following output:

storage = 101
∞梦里开花 2024-07-27 06:25:34

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

  • 公共-> 基类的公共成员将是公共的(通常是默认的)
  • 受保护-> 基类的公共成员将受到保护
  • 私人-> 基类的公共成员将是私有的

正如 litb 指出的那样,公共继承是您在大多数编程语言中都会看到的传统继承。 也就是说,它模拟了“IS-A”关系。 私有继承,据我所知是 C++ 所特有的,是一种“根据……实现”的关系。 也就是说,您希望在派生类中使用公共接口,但不希望派生类的用户能够访问该接口。 许多人认为,在这种情况下,您应该聚合基类,也就是说,不要将基类作为私有基,而是在派生类的成员中创建以便重用基类的功能。

It has to do with how the public members of the base class are exposed from the derived class.

  • public -> base class's public members will be public (usually the default)
  • protected -> base class's public members will be protected
  • private -> base class's public members will be private

As litb points out, public inheritance is traditional inheritance that you'll see in most programming languages. That is it models an "IS-A" relationship. Private inheritance, something AFAIK peculiar to C++, is an "IMPLEMENTED IN TERMS OF" relationship. That is you want to use the public interface in the derived class, but don'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's functionality.

︶葆Ⅱㄣ 2024-07-27 06:25:34
Member in base class : Private   Protected   Public   

继承类型:           对象继承为

Private            :   Inaccessible   Private     Private   
Protected          :   Inaccessible   Protected   Protected  
Public             :   Inaccessible   Protected   Public
Member in base class : Private   Protected   Public   

Inheritance type :             Object inherited as:

Private            :   Inaccessible   Private     Private   
Protected          :   Inaccessible   Protected   Protected  
Public             :   Inaccessible   Protected   Public
强辩 2024-07-27 06:25:34
  1. 公共继承:

    a. 基类的私有成员在派生类中不可访问。

    b. 基类的受保护成员在派生类中仍受保护。

    c. 基类的公共成员在派生类中仍然是公共的。

    因此,其他类可以通过派生类对象使用基类的公共成员。

  2. 受保护的继承:

    a. 基类的私有成员在派生类中不可访问。

    b. 基类的受保护成员在派生类中仍受保护。

    c. 基类的公共成员也成为派生类的受保护成员。

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

  3. 私有继承:

    a. 基类的私有成员在派生类中不可访问。

    b. 受保护和 基类的公共成员成为派生类的私有成员。

    因此,其他类不能通过派生类对象访问基类的任何成员,因为它们在派生类中是私有的。 因此,即使派生类的子类也无法访问它们。

  1. Public Inheritance:

    a. Private members of Base class are not accessible in Derived class.

    b. Protected members of Base class remain protected in Derived class.

    c. Public members of Base class remain public in Derived class.

    So, other classes can use public members of Base class through Derived class object.

  2. Protected Inheritance:

    a. Private members of Base class are not accessible in Derived class.

    b. Protected members of Base class remain protected in Derived class.

    c. Public members of Base class too become protected members of Derived class.

    So, other classes can't use public members of Base class through Derived class object; but they are available to subclass of Derived.

  3. Private Inheritance:

    a. Private members of Base class are not accessible in Derived class.

    b. Protected & public members of Base class become private members of Derived class.

    So, no members of Base class can be accessed by other classes through Derived class object as they are private in Derived class. So, even subclass of Derived class can't access them.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文