Difference between private, public, and protected inheritance
EDCOX1、0、EDCX1、1、EDCX1和2的遗传差异在C++中有什么不同?我发现的所有问题都要处理特定的案例。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | 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。这只是访问问题。
关于受保护和私有继承的使用,您可以在这里阅读。
为了回答这个问题,我想先用我自己的话来描述成员的访问器。如果您已经知道这一点,请跳到标题"下一步:"。
我知道有三个附加器:
让:
1 2 3 4 5 6 7 8 | class Base { public: int publicMember; protected: int protectedMember; private: int privateMember; }; |
- 所有了解
Base 的人都知道Base 包含publicMember 。 - 只有孩子(和他们的孩子)知道
Base 包含protectedMember 。 - 除了
Base 以外,没有人知道privateMember 。
"意识到",我的意思是"承认存在,从而能够进入"。
下一步:公共继承、私有继承和受保护继承也是如此。让我们考虑一个类
- 如果遗产是
public ,那么所有知道Base 和Child 的人也都知道Child 继承自Base 。 - 如果遗产是以东十一〔1〕号,只有以东十一〔11〕号及其子女知道他们是从以东十一〔3〕号继承的。
- 如果遗产是以东十一〔2〕号,除以东十一〔11〕号外,没有人知道该遗产。
限制继承的可见性将使代码看不到某些类继承了另一个类:从派生到基的隐式转换将不起作用,并且从基到派生的
只有类的成员/朋友可以看到私有继承,只有成员/朋友和派生类可以看到受保护的继承。
公共继承
是继承。按钮是一个窗口,在任何需要窗口的地方,也可以传递一个按钮。
1 | class button : public window { }; |
受保护的继承
根据实施保护。很少有用。在
1 2 3 4 5 6 7 8 9 10 11 12 | 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! } }; |
私人继承
根据实施。基类的用法仅用于实现派生类。对于特性和大小都很有用(只包含函数的空特性将利用空基类优化)。不过,遏制往往是更好的解决方案。字符串的大小非常关键,因此在这里经常使用
1 2 3 4 5 6 7 8 | template<typename StorageModel> struct string : private StorageModel { public: void realloc() { // uses inherited function StorageModel::realloc(); } }; |
公众成员
骨料
1 2 3 4 5 | class pair { public: First first; Second second; }; |
访问器
1 2 3 4 | class window { public: int getWidth() const; }; |
受保护成员
为派生类提供增强的访问
1 2 3 4 5 6 7 8 9 | class stack { protected: vector<element> c; }; class window { protected: void registerClass(window_descriptor w); }; |
私人成员
保留实施详细信息
1 2 3 4 | class window { private: int width; }; |
注意,C样式的强制转换有目的地允许以一种定义的、安全的方式将派生类强制转换为受保护的或私有的基类,并且也允许强制转换到另一个方向。应该不惜一切代价避免这种情况,因为它可以使代码依赖于实现细节——但如果必要,您可以使用这种技术。
它与如何从派生类中公开基类的公共成员有关。
- public->基类的public成员将是public(通常为默认值)
- protected->将保护基类的公共成员
- private->基类的公共成员将是private
正如Litb指出的那样,公共继承是传统继承,在大多数编程语言中都可以看到。也就是说,它塑造了一种"即是即是"的关系。私有继承,是C++特有的东西,是一种"以关系来实现"的关系。也就是说,您希望在派生类中使用公共接口,但不希望派生类的用户有权访问该接口。许多人认为,在这种情况下,应该聚合基类,也就是说,为了重用基类的功能,应该将基类作为派生的成员,而不是将基类作为私有的基。
这三个关键字也用于完全不同的上下文中,以指定可见性继承模型。
此表收集组件声明和继承模型的所有可能组合,当子类完全定义时,这些组合表示对组件的最终访问。
上表的解释方法如下(请看第一行):
if a component is declared as public and its class is inherited as public the resulting access is public.
一个例子:
1 2 3 4 5 6 7 8 9 | class Super { public: int p; private: int q; protected: int r; }; class Sub : private Super {}; class Subsub : public Sub {}; |
类中的变量
Another example:
1 2 3 4 5 6 | class Super { private: int x; protected: int y; public: int z; }; class Sub : protected Super {}; |
类Sub中的变量
A more detailed example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 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; } |
现在让我们定义一个子类:
1 2 3 4 5 6 7 8 9 10 | class Sub : Super { }; int main(void) { Sub object; object.put(100); object.put(object.get()); cout << object.get() << endl; return 0; } |
一个名为sub的定义类,它是名为
不,没有。
如果我们编译以下代码,只会得到编译错误,说明无法访问
当我们省略可见性说明符时,编译器假定我们要应用所谓的私有继承。这意味着所有公共超类组件都变成了私有访问,私有超类组件根本无法访问。因此,它意味着不允许在子类中使用后者。
我们必须通知编译器我们要保留以前使用的访问策略。
1 | 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.
这是一个非常严重的限制。有什么解决办法吗?
对。
第三个访问级别称为"受保护"。关键字protected意味着当被任何子类使用时,用它标记的组件的行为类似于公共组件,在世界其他地方看起来像私有组件。--这只适用于公开继承的类(比如我们示例中的超级类)。--
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | 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; } |
正如您在示例代码中看到的,我们为
如果变量声明为private,则不可能。在主函数范围内,变量始终保持隐藏状态,因此,如果编写如下内容:
1 | object.storage = 0; |
编译器将通知您它是一个
最后,最后一个程序将产生以下输出:
1 | storage = 101 |
1 | Member in base class : Private Protected Public |
继承类型:继承对象为:
1 2 3 | Private : Inaccessible Private Private Protected : Inaccessible Protected Protected Public : Inaccessible Protected Public |
1)公共继承:
a.基类的私有成员在派生类中不可访问。
B.基类的受保护成员在派生类中保持受保护。
c.基类的公共成员在派生类中保持公共。
因此,其他类可以通过派生类对象使用基类的公共成员。
2)受保护的继承:
a.基类的私有成员在派生类中不可访问。
B.基类的受保护成员在派生类中保持受保护。
c.基类的公共成员也成为派生类的受保护成员。
因此,其他类不能通过派生类对象使用基类的公共成员;但它们可用于派生类的子类。
3)私有继承:
a.基类的私有成员在派生类中不可访问。
B.基类的受保护和公共成员成为派生类的私有成员。
因此,其他类不能通过派生类对象访问基类的成员,因为它们在派生类中是私有的。所以,即使是派生的子类类无法访问它们。
公共继承为IS-A关系建模。用
1 2 | class B {}; class D : public B {}; |
每个
私有继承为正在实现的使用关系(或调用的任何关系)建模。用
1 2 | class B {}; class D : private B {}; |
1 2 3 4 5 | class B {}; class D { private: B b_; }; |
这个
我认为没有人知道什么是
如果您从另一个类公开继承,那么每个人都知道您正在继承,并且任何人都可以通过基类指针多态地使用您。
如果您受到保护地继承,那么只有您的子类才能多态地使用您。
如果您私下继承,那么只有您自己才能执行父类方法。
这基本上代表了其他班级对你和你的家长班级关系的了解。
从类继承的任何类都可以访问受保护的数据成员。但是,私有数据成员不能。假设我们有以下内容:
1 2 3 4 5 6 | class MyClass { private: int myPrivateMember; // lol protected: int myProtectedMember; }; |
从这个类的扩展范围内,引用
1 2 3 4 5 6 7 8 9 10 11 12 | 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…我想一张小桌子值一千个字:)
总结:
- private:除了在课堂上,没有人能看到它。
- 受保护:私有+派生类可以看到它
- 公众:全世界都能看到
继承时,可以(在某些语言中)在特定方向上更改数据成员的保护类型,例如从"受保护"更改为"公共"。
私人:
基类的私有成员只能由该基类的成员访问。
公众:基类的公共成员可以由该基类的成员、其派生类的成员以及基类和派生类之外的成员访问。
受保护的:基类的受保护成员可以由基类成员及其派生类成员访问。
简而言之:私人:基地
受保护:基础+衍生
public:基+派生+任何其他成员
我找到了一个简单的答案,所以想把它贴出来,以备将来参考。
它来自链接http://www.learncpp.com/cpp-tutorial/115-inheritance-and-access-specifiers/
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | 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 } |
它本质上是对派生类中基类的公共成员和受保护成员的访问保护。通过公共继承,派生类可以看到基的公共成员和受保护成员。有了私有继承,就不能了。有了保护,派生类和从中派生的任何类都可以看到它们。