私人,公共和受保护的inheritance之间的区别

C ++中publicprivateprotectedinheritance之间的区别是什么? 我在SO上发现的所有问题都是针对具体案例的。

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

有三个访问者,我知道: publicprotectedprivate

让:

 class Base { public: int publicMember; protected: int protectedMember; private: int privateMember; }; 
  • 所有知道Base都知道Base包含publicMember
  • 只有孩子(和他们的孩子)知道Base包含protectedMember
  • Base没有人知道privateMember

“意识到”,我的意思是“承认存在,从而能够存取”。

下一个:

公共,私有和受保护的inheritance也是如此。 我们来考虑一个类Base和一个从Baseinheritance的类Child

  • 如果inheritance是public ,那么知道BaseChild所有东西都知道ChildBaseinheritance。
  • 如果inheritance是protected ,则只有Child和它的子节点知道它们inheritance自Base
  • 如果inheritance是privateChild以外的任何人都不知道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 }; 

重要提示:类B,C和D都包含variablesx,y和z。 这只是访问的问题。

关于保护和私有inheritance的使用,你可以在这里阅读。

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

只有类的成员/朋友可以看到私有inheritance,只有成员/朋友和派生类可以看到受保护的inheritance。

公共inheritance

  1. IS-Ainheritance。 一个button是一个窗口,并且在任何需要窗口的地方,一个button也可以被传递。

     class button : public window { }; 

受保护的inheritance

  1. 受保护的实施条款。 非常有用。 在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! } }; 

私人inheritance

  1. 实现合条件方面。 基类的用法仅用于实现派生类。 有用的性状,如果大小很重要(空function只包含function将利用空基类优化)。 然而,通常遏制是更好的解决scheme。 string的大小是至关重要的,所以这是一个常见的用法

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

公众成员

  1. 骨料

     class pair { public: First first; Second second; }; 
  2. 访问器

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

保护成员

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

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

私人会员

  1. 保持实施细节

     class window { private: int width; }; 

请注意,C风格强制转换允许以定义和安全的方式将派生类转换为受保护的或私有的基类,并向另一方向投射。 这应该不惜一切代价避免,因为它可以使代码依赖于实现细节 – 但是如果有必要的话,你可以使用这种技术。

它与基类的公共成员如何从派生类中暴露出来有关。

  • 公共 – >基类的公共成员将公开(通常是默认的)
  • 保护 – >基地的公共成员将受到保护
  • 私人 – >基层的公众成员将是私人的

正如litb指出的那样,公有inheritance是传统的inheritance,你会在大多数编程语言中看到。 这就是模拟“IS-A”关系。 私有inheritance是C ++特有的AFAIK,是一个“实现的术语”关系。 那就是你想在派生类中使用公共接口,但不希望派生类的用户有权访问该接口。 许多人认为,在这种情况下,您应该聚合基类,而不是将基类作为私有基类,而是在派生成员中进行重用,以重用基类的function。

 Member in base class : Private Protected Public 

inheritancetypesObjectinheritance为

 Private : Inaccessible Private Private Protected : Inaccessible Protected Protected Public : Inaccessible Protected Public 

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

这个表格收集组件声明和inheritance模型的所有可能的组合,当子类被完全定义时,该模型呈现对组件的结果访问。

在这里输入图像描述

它读取方式如下(看第一行):

如果一个组件被声明public,并且它的类被inheritancepublic,那么最终的访问公共的

一个例子:

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

Subsub中variablespqr的结果访问是none

另一个例子:

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

Sub类中variablesyz的结果访问被保护 ,而variablesx 没有

更详细的例子:

 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的类名为Sub,该类名为SuperSub类的Sub类是从Super类派生的。 Sub类既不引入新的variables也不引入新的函数。 这是否意味着Sub类的任何对象都inheritance了Super类实际上是Super类对象的副本之后的所有特征?

没有 。 它不。

如果我们编译下面的代码,我们将得到什么,但编译错误,说putget方法是无法访问的。 为什么?

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

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

 class Sub : public Super { }; 

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

Sub类的对象可能与“ Super类创build的更老的兄弟姐妹“几乎”是一样的。 “几乎”是因为作为子类的事实也意味着类失去了对超类私有组件的访问 。 我们不能写一个能够直接操作存储variables的Sub类的成员函数。

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

是的

第三个访问级别被称​​为保护 。 关键字保护意味着用它标记的组件在被任何子类使用时performance得像公共的一样,看起来像是世界其他地方的私有组件 。 – 这只适用于公开inheritance的类(比如我们例子中的超级类)

 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类创build了一个新的function,并且它做了一件重要的事情: 它从Super类访问存储variables

如果这个variables被声明为私有的话,这是不可能的。 在主要的函数范围内,variables仍然是隐藏的,所以如果你写下类似的东西:

 object.storage = 0; 

编译器会通知你这是一个error: 'int Super::storage' is protected

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

 storage = 101 

1)公共inheritance

一个。 Derived类中不能访问Base类的私有成员。

湾 基类的受保护成员在Derived类中保持保护。

C。 Base类的公共成员在Derived类中保持公共。

所以其他类可以通过Derived类对象使用Base类的public成员。

2)受保护的inheritance

一个。 Derived类中不能访问Base类的私有成员。

湾 基类的受保护成员在Derived类中保持保护。

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

所以其他类不能通过Derived类对象使用Base类的public成员; 但它们可用于Derived的子类。

3)私人inheritance

一个。 Derived类中不能访问Base类的私有成员。

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

因此,没有其他类的成员可以通过派生类对象访问,因为它们是派生类中的私有类。 所以,即使Derived类的子类也不能访问它们。

公共inheritancebuild模一个IS-A关系。 同

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

每个D 是一个 B

私有inheritancebuild模一个IS-IMPLEMENTED-USING关系(或者其他所谓的)。 同

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

D 不是 B ,但是每个D在其实现中都使用它B 私有inheritance总是可以通过使用遏制来消除:

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

这个D也可以用B来实现,在这种情况下用B来实现。 遏制是types间的紧密耦合而不是inheritance,所以一般来说它应该是优选的。 有时使用遏制而不是私有inheritance不如私有inheritance方便。 往往这是懒惰的蹩脚的借口。

我不认为有人知道什么protected遗传模型。 至less我还没有看到有说服力的解释。

如果你从另一个类公开inheritance,每个人都知道你是inheritance的,你可以通过基类指针被多态使用。

如果你inheritance保护,只有你的孩子类将能够使用多态。

如果你只是私下inheritance,你自己将能够执行父类的方法。

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

受保护的数据成员可以由任何inheritance自类的类访问。 私人数据成员,但是,不能。 假设我们有以下几点:

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

从你的扩展到这个类中,引用this.myPrivateMember将不起作用。 但是, this.myProtectedMember会。 该值仍然是封装的,所以如果我们有一个名为myObj类的实例化,那么myObj.myProtectedMember将不起作用,所以它在function上类似于私有数据成员。

 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 

基于java的这个例子…我认为一个小小的表值得千言万语:)

概要:

  • 私人:除了在课堂之外,没有人能看到它
  • 受保护:私有+派生类可以看到它
  • 公众:世界可以看到它

当inheritance的时候,你可以(用某种语言)改变一个数据成员在某个方向上的保护types,例如从保护到公共。

私人的:

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

上市:

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

保护:

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


简而言之:

私人 :基地

保护 :基地+派生

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

它本质上是派生类中的基类的受保护成员和公共访问保护。 通过公共inheritance,派生类可以查看基类的公共和受保护成员。 有了私有inheritance,它不能。 在受保护的情况下,派生类和从派生类派生的任何类都可以看到它们。

我find了一个简单的答案,所以也想过把它发布给我以后的参考。

它来自链接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 } 

看到这些代码了解c ++有关inheritance的function…我把结果放在最后…希望它有帮助。

 #include <iostream> using namespace std; class A { private: void pri(); A(int a); protected: virtual void pro() {} public: void pub1() { cout<<"A.pub1()\n"; } virtual void pub2() { cout<<"A.pub2()\n"; } virtual void pub3() { cout<<"A.pub3()\n"; } virtual void pub4() { cout<<"A.pub4()\n"; } virtual void pub5() { cout<<"A.pub5()\n"; } virtual void pub6() { cout<<"A.pub6()\n"; } virtual void pub7() { cout<<"A.pub7()\n"; } virtual void pub8() { cout<<"A.pub8()\n"; } void pub9() { cout<<"A.pub9()\n"; } virtual void pub10() { cout<<"A.pub10()\n"; } void pub11() { cout<<"A.pub11()\n"; } explicit A() {} virtual ~A() {} }; class B : public A { private: void pri() { cout<<"B.pri()\n"; } protected: virtual void pub4() { cout<<"B.pub4()\n"; } void pub6() { cout<<"B.pub6()\n"; } public: void pro() { cout<<"B.pro() "; B::pri(); } void pub1() { cout<<"B.pub1()\n"; } void pub2() { cout<<"B.pub2()\n"; } void pub5() { cout<<"B.pub5()\n"; } virtual void pub7() { cout<<"B.pub7()\n"; } virtual void pub8() { cout<<"B.pub8()\n"; } virtual void pub9() { cout<<"B.pub9()\n"; } void pub10() { cout<<"B.pub10()\n"; } void pub11() { cout<<"B.pub11()\n"; } explicit B() {} }; class C : protected B { public: void pub4_() { cout<<"C.pub4_() "; B::pub4(); } virtual void pub5() { cout<<"C.pub5()\n"; } }; class D : private B { public: void pub4_() { cout<<"D.pub4_() "; B::pub4(); } }; class E : public B { public: virtual void pub4() { cout<<"E.pub4()\n"; } virtual void pub7() { cout<<"E.pub7()\n"; } virtual void pub8() { cout<<"E.pub8()\n"; } virtual void pub9() { cout<<"E.pub9()\n"; } virtual void pub10() { cout<<"E.pub10()\n"; } virtual void pub11() { cout<<"E.pub11()\n"; } }; void testClasses() { A* ap=new B(); ap->pub1(); // == A::pub1() //important // (new B()).pub1() can't override non-virtual A::pub1() for an A* pointer. ap->pub2(); // == B::pub2() //important // (new B()).pub1() can override virtual A::pub1() for an A* pointer. B b; bA::pub1(); b.pro(); B* bp=new B; bp->pub3(); C c; //c.pub3(); //error //c.pub4(); //error c.pub4_(); c.pub5(); D d; //d.pub3(); //error //d.pub4(); //error d.pub4_(); E e; //e.pub4(); //error delete ap; ap = new E(); ap->pub4(); ap->pub5(); ap->pub6(); ap->pub7(); delete bp; bp = new E(); e.pub8(); eA::pub8(); eB::A::pub8(); eB::pub8(); ap->pub8(); bp->pub8(); e.pub9(); eA::pub9(); eB::A::pub9(); eB::pub9(); ap->pub9(); // important bp->pub9(); e.pub10(); eA::pub10(); eB::A::pub10(); eB::pub10(); ap->pub10(); // important bp->pub10(); // very important... eventhough B::pub10() is non-virtual, // bp->pub10() != b.pub10(); e.pub11(); eA::pub11(); eB::A::pub11(); eB::pub11(); ap->pub11(); bp->pub11(); delete ap; delete bp; return; } int main() { testClasses(); return 0; } ///////////////////////////////////////// ........ Result : ........ A.pub1() B.pub2() A.pub1() B.pro() B.pri() A.pub3() C.pub4_() B.pub4() C.pub5() D.pub4_() B.pub4() E.pub4() B.pub5() B.pub6() E.pub7() E.pub8() A.pub8() A.pub8() B.pub8() E.pub8() E.pub8() E.pub9() A.pub9() A.pub9() B.pub9() A.pub9() E.pub9() E.pub10() A.pub10() A.pub10() B.pub10() E.pub10() E.pub10() E.pub11() A.pub11() A.pub11() B.pub11() A.pub11() B.pub11()