#include<iostream>
using namespace std;
class uvw;
class abc{
private:
int privateMember;
protected:
int protMember;
public:
int publicMember;
};
class def : private abc{
public:
void dummy_fn();
};
class uvw: public def{
};
void def::dummy_fn()
{
abc x;
def y;
uvw z;
cout << z.protMember << endl; // This can be accessed and doesn't give a compile-error
}
根据我的理解,def
私下从abc
继承后,protMember
和publicMember
在def
中变为私有。所以,现在当uvw
继承自def
时,它不应该有任何数据成员。但我们可以从z.protMember
奇怪地访问dummy_fn()
,其中z
首先不应该有变量protMember
。我在哪里出错了?
答案 0 :(得分:6)
如果您尝试从免费功能访问它,它将无法正常工作。它在这种情况下有效,因为dummy_fn()
是def
的成员函数,因此它可以访问def
内的所有私有内容。由于z
是-a def
,因此它也可以访问def
个实例中的私有z
成员。
或者至少这是我的猜测。这是一个奇怪的案例。
答案 1 :(得分:3)
你偶然发现了C ++静态(而不是动态)输入的后果;因此,访问检查在编译时(而不是运行时)执行,从而推断变量的可见类型,而不是实际动态类型(这是一个运行时属性)。
解开一点例子:
class Base { protected: int prot; };
class Derived: private Base { void func(); };
void Derived::func() { std::cout << prot << std::endl; }
func
是Derived
的成员,因此它可以访问Derived
的所有数据成员,包括直接和可通过继承访问:
Derived
直接从Base
继承,因此可以访问Base
prot
在protected
中为Base
,因此任何可以访问prot
的儿童都可以访问Base
因此,prot
可以访问Derived
(因此在Derived::func
中)。
让我们展示访问路径的重要性:
class Another: private Base {};
class YetAnother: public Another { void func(); };
void YetAnother::func() { std::cout << prot << std::endl; } // ERROR (access)
此处,即使Base::prot
中可以访问Another
,因为Another
隐藏了从Base
继承到其他所有人的事实,YetAnother
无法访问Base
{1}}因此,传递上,无法访问Base::prot
。
让我们展示静态类型的效果:
class Basic { void func(); };
class More: public Basic { public: int a; };
void Basic::func() { std::cout << a << std::endl; } // ERROR (unknown)
在这里,即使More
对象有a
成员,但在编译Basic
时,我们只能依赖Basic
知道的内容。 Basic
不知道a
。
将此与Python等动态语言进行对比,对于没有More
的人来说,这对于类AttributeError
的对象运行正常并且失败(a
异常)。
答案 2 :(得分:2)
私有继承仅限制来自类外部的访问。它不限制派生类从基类中看到的内容。因此,在def
abc
私密地从def
继承的情况下,abc
仍然可以访问def
的所有受保护成员。只有abc
的客户才能访问publicMember
中的任何内容;甚至不是uvw
。
另外,不要将私有继承与不继承成员或其他内容混淆。
所以,现在当uvw从def继承时,它不应该有任何数据成员。
这种说法不正确。
abc
同样拥有def
和{{1}}所拥有的任何数据成员,只能从外部访问它们。
参见例如详情请见http://www.learncpp.com/cpp-tutorial/115-inheritance-and-access-specifiers/