• 认真地记录技术中遇到的坑!

8.1类的访问控制与封装

C/C++ Moxun 2年前 (2018-01-22) 532次浏览 0个评论

[toc]前导:
通过class关键字实现对类的封装,另外还可以通过“访问说明符”加强类的封装特性(就是提供访问权限的说明),关键字class和关键字struct的区别就是,(在第一个访问说明符之前)如果不使用访问说明符限制,那么它的所有成员都是私有的,只能由类自己使用,而在同样情况下,struct的成员是公有的。
访问说明符说明:
public:定义在public之后的成员可以在程序内访问,public成员定义类的接口。(公有继承)
private:定义在private之后的成员只能供类自己使用使用(类的对象甚至它的子类都不能使用),该关键字部分封装了类的实现细节。
protected:(假设继承是public或者protected的),定义在protected之后的成员只能由类本身以及其子类使用。

    一个类可以可以包含0个或多个访问说明符,对某个具体的访问说明符能出现的次数也没有限制。

[toc]8.1.1友元
类可以允许其他类或者函数访问它的非公有成员,方法是令其它类或者函数成为它的友元,此时只需要增加一条以friend关键字开始的函数声明语句即可。友元声明只能出现在类的内部,但是具体出现在哪里是没有要求的,友元的访问权限不受访问说明符的限制。

    封装的两个优点:
    1.确保用户代码不会无意间破坏封装对象的状态
    2.被封装的类的具体实现细节可以随时改变而不用调整用户级代码。

    友元函数的声明仅仅指定了访问的权限,而不是一个通常意义上的函数声明,如果我们希望类的用户能调用某个友元函数,那么我们必须在友元声明之外再专门对函数进行一次声明。为了使友元对类的用户可见,那么我们通常把友元的声明和类本省放在一个头文件里。友元函数本身的声明最好放在友元(friend)声明之前。

[toc]8.2.2
类还可以自定义某种类型在类中的别名,由类定义的类型名字和其它成员一样存在访问限制,可以是public、private、protected中的一种。用来定义类型的成员必须要先定义后使用,因此,类型定义通常出现在类开始的地方。
成员函数也可以重载,函数匹配过程与普通成员函数一样。
可变数据成员:有时我们希望可以改变类的某个数据成员,即使是在一个const成员函数内。此时,我们通过在变量的声明中加入mutable关键字做到这一点。此时,即使是const成员函数也可以改变mutable修饰的成员。

    类的数据成员的默认值:C++新标准中,这些成员最好使用类内初始值。提供类内初始值时必须使用“=”或者“{}”。

[toc]8.2.3 返回this的成员
还记得this指针的?this是调用方法或者属性的对象的指针(指向该对象),它是一个常量指针。cosnt成员方法,是使this指针指向了一个const对象,在这类方法中我们不能修改类的数据成员。

    return *this;意味着方法返回的是调用方法对象的引用而非副本值,这是一个左值。
    如果一个const成员方法 使用了(return *this),那么它返回的是一个常量引用。

[toc]8.2.4 基于const的重载
通过区分方法是否是const的,可以对成员进行重载。因此非常量版本的函数对于常量是不可用的(因为非常量版本的函数会有可能改变数据成员)。虽然,可以在非常量对象上调用常量版本或非常量版本的函数。一个成员在使用另一个成员时,this指针在隐式的传递。对于公共代码我们应该使用私有功能函数,一个大的函数往往由一些小函数构成,这些小函数会有可被设计为内联函数的潜力。

[toc]8.2.5 类类型
每个类定义了唯一的类型,即使这两个类的成员完全一样。类的名字就是类型名,也可以在类名前面跟上class或者struct关键字。

类的声明:
可以仅声明类而不定义它,例如:
class A;
这种声明被称为前向声明,它向程序引入了一个名为A的类类型,对于类型A来说,在它声明之后,定义之前是一个不完全类型,因为我们不清楚它包含哪些类型。可以定义指向这种类型的指针或者引用也可以声明以不完全类型作为参数或者返回类型的函数。
对于宇哥类来说,在我们创建它的对象时该类必须定义过,不能仅仅被声明,否则,编译器就不知道这样的对象到底需要多少存储空间,类似的,类必须首先被定义,才能用引用或者指针访问其成员。

    直到类定义之后,数据成员才能被声明为这种类型,所以一个类的成员类型不能是自己,然而一个类的名字出现后,它就被认为是声明过了,因此类允许有指向它自身类型的引用或者指针。(这是链表的理论基础)

[toc]8.2.6友元
类的友元可以是普通函数、其它类也可以是其它类的成员函数,此外,友元函数可以定义在类的内部,这样的函数是隐式内联的。
类之间的友元关系
如果一个类指定了友元类,则友元类的成员函数可以访问此类包括非公有成员在内的所有成员。此外,友元不具有传递性,即B使C的友元,A是B的友元,但A不是C的友元。每个类负责控制自己的友元类或者友元函数。

令成员函数做友元:
当把一个成员函数声明为友元时,必须明确的指出该成员属于哪个类。
例如:
class Screen{
friend void Window_mgr::clear(ScreenIndex);
};

    要想使某个成员函数作为友元,我们必须仔细组织程序的组织结构以满足声明和定义的彼此依赖关系,需要满足以下关系:
    首先定义Window_mgr类,其中声明clear函数,但是不能定义它。在clear使用Screen的成员之前必须先声明Screen。
    接下来定义Screen,包括对于clear的友元声明
    最后定义clear,此时它才可以使用Screen的成员。

函数重载和友元
如果一个类想把一组重载函数声明为它的友元,那么它需要对这组函数的每一个分别声明
友元声明和作用域:
类和非成员函数的声明不是必须在它们的友元声明之前,当一个名字第一次出现在一个友元声明中是,我们隐式的假定该名字在当前作用域中是可见的,然后友元本身并不一定真的声明在当前作用域中。甚至就算在类的内部定义该函数,我们也必须在类的外部提供相应的声明从而使得函数可见。即使我们仅仅是用声明友元的类的成员调用该友元函数,它也必须是被声明过的,例如:
struct x{
friend void f(){友元函数可以定义在类的内部};
X() {f();}
void g();
void h();
}
void X::g(){return f();} //这个写法是错误的,因为,在此时函数f还有没有被声明。

    void f();
    void X::h() { return f();}

转载请注明出处 8.1类的访问控制与封装
喜欢 (0)
发表我的评论
取消评论
表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址