[原]C++:再谈基础之访问权限

C++里提供了三种访问权限:public、protected,以及private。分别代表对所有公开,对部分公开,完全不公开。这三个关键字不但能够作为access label,也可以用于指定继承方式。

在开始之前,先看看scope和C++的对象模型。在一个类的实例中,其相应的类的成员函数并不是包含在实例的内存区里。因此,每个non-static的成员函数在访问同类其他成员时会有一个隐含的参数this。*this代表调用该函数的实例——也就是说用于识别实例。因此:

AccessPermDemo::SomeType AccessPermDemo::GetSomeTypeMember()
{
    return m_SomeType; // Actually "return this->m_SomeType;"
}


编译之后这段代码可能就成为:

int __AccessPermDemo_GetSomeTypeMember(AccessPermDemo * this)
{
    return this->m_SomeType;
}


另外,这段代码还展示了另外一个概念:scope。一个类的成员函数,其返回值与函数实现(名字、参数列表、函数体)所处的scope不同,因此需要分别指定其所属scope。对于定义(注意声明和定义的区别)在类定义内——准确的说是函数体写在类定义内的函数,整个函数体都处在该类的scope中。因此当上面的函数这样写时:

class AccessPermDemo
{
//...
    inline SomeType GetSomeTypeMember() { return m_SomeType }
// ...
};

这里涉及到inline以及binary compatiblity问题超出本文的scope,不做讨论。

好了,现在可以开始了。

首先,我们来看public

public表示其后所定义的成员对程序所有的部分可见,这里的成员包括:数据成员、成员函数以及类型。其实准确的说:public修饰的成员对于class scope内外的部分都是可见的。如:

class AccessPermDemo
{
public:
    typedef int SomeType;
    AccessPermDemo();
    int m_PublicMem;
 

这里包括了三种情况。这表明,这三个成员可以被程序的任意一个地方访问到。我想,这相当简单,无须赘述:

AccessPermDemo demo = AccessPermDemo(); // Access public ctor
demo.m_Public = 0; // Access public data member
AccessPermDemo::SomeType a = demo.GetSomeTypeMember(); // Access public member function and type


当public用于继承时,表示其后的类被作为子类的一个public的部分。基类中public成员依然对全世界开放,而private成员只对基类scope内可见。

Derived der;
der.GetSomeTypeMember(); // GetSomeTypeMember() accessible outside scope of AccessPermDemo


private
修饰成员时,表示该成员仅在该类的scope内可见。参考第一段代码。要注意一种情况,那就是在成员函数中访问同类参数的私有成员,如copy ctor和operaotr ==():

AccessPermDemo::AccessPermDemo(const AccessPermDemo& aDemo)
{
    this->m_SomeType = aDemo.m_SomeType;
}

这里显示指出this是为了表明,在同一个类的scope中,可以访问该类的私有成员,但需要指明访问的是哪个instance的数据成员,或者以哪个instance作为this参数传递给成员函数。

当继承方式为private时,基类作为子类的一个私有部分。因此,在子类的scope中可以访问到基类的public成员——这时可以把基类视作子类的一个私有成员。此时基类的private成员依然不可访问。

protected
这是最复杂的一种情况,因此在很多借鉴了C++设计思想的语言里都消除了protected。对于这个部分我了解不多,这里就大致说一下吧——为了这篇文章的完整性。希望有大牛来指点一下!

protected成员表明,该成员在类及其子类的scope内可访问,该scope外不可访问。如果在基类scope外的同时又不处于子类的scope中,该成员就是不可访问的。而在子类的scope中,它就是private的,仅在该scope内可访问。如下图:


当使用protected继承时,可以将基类视作子类protected的一部分。

参考:
Inside the C++ Object Model, 2nd ed, by Stanly B Lippman
C++ Primer, 4th ed, by Stanly B. Lippman
The C++ programming Language, special ed, by Bjarne Stroustup

PS:坦白说,每次我写关于C++的某个专题,就会牵涉到很多其他的问题,让我总觉得自己不能非常清楚地讲明白这个专题——也许是我太笨吧。

再PS:以后要不要用e文来写blog呢?用e文写肯定会降低点击率的,但对自己的e文会有提高。考虑中……

Copyleft (C) 2007-2009, raof01.
本文可以用于除商业外的所有用途。此处“用途”包括(但不限于)拷贝/翻译(部分或全部),不包括根据本文描述来产生代码及思想。若用于非商业,请保留此权利声明,并标明文章原始地址和作者信息;若要用于商业,请与作者联系(raof01@gmail.com),否则作者将使用法律来保证权利。
posted on 2009-01-10 16:55  raof01  阅读(163)  评论(0编辑  收藏  举报