C++编程思想学习笔记---第五章 隐藏实现

来源:互联网 发布:淘宝账号怎么找回 编辑:程序博客网 时间:2024/05/29 03:58

第5章 隐藏实现


一、C++的访问控制符

public 在其后声明的所有成员可以被所有人访问。

private 表示除了该类型的创建者类的内部成员函数之外,任何人都不能访问。

protected 继承的结构可以访问protected成员,但不能访问private结构


二、友元:朋友才能看到

C++是一种很“人性化”的语言,跟我不熟的人,都不能知道我家的家庭成员。朋友就可以。

可以声明为友元的函数类型:

1、全局函数(可以用本结构的指针作为参数)

2、另一个结构中的函数(可以用本结构的指针作为参数)

3、整个另一个结构

friend的双重声明作用:1) 声明一个函数

   2) 声明这个函数为当前结构的友元


开个小差:书中有这样一个代码段

struct X;struct Y{    void f(X*);};

结构Y要声明其成员函数f(X*),必须知道X的定义,但X结构体又是在结构Y之后明确定义的。这种情况下可以在前面先声明一个struct X。函数要传递的是一个地址,不关X是什么类型,其类型的地址都是一个固定的值,因此编译器知道如何传递一个地址。编译是可以通过的。

但是如果声明这样一个函数void f(X);就不行了,因为编译器还不知道X的具体结构,编译会报错。


三、嵌套友元

嵌套的结构并不能自动获得访问private成员的权限。若遵循下列规则就可以

1、声明一个嵌套结构

2、声明该结构为全局范围的friend

3、定义这个结构

主要就是将声明结构与声明友元分开~!

struct Holder{private:int a[sz];public:void initialize();struct Pointer;friend Pointer;struct Pointer{private:Holder* h;int* p;public:void initialize(Holder* h);void next();void previous();void top();void end();int read();void set(int i);};};

这样,结构Pointer就可以直接访问数组a了。

再做个试验,在public区域定义一个变量int n; 如果并没有声明结构Pointer是结构Holder的友元,结构Pointer的函数仍然能够访问数据成员n。这说明,friend关键字是用来让外部函数访问类的私有成员的一种方法!!!

从第三点看出,C++并非一个纯面向对象的语言,friend关键字用来解决一些实际问题。


五、类

关键字class被用来描述一个新的数据类型。它和struct的每一个方面都是一样的,不同在于

class声明的类中的成员默认为private;

struct声明的结构体中的成员默认为public;


六、现在以C++的方式来实现一个Stash

#ifndef STASH_H#define STASH_Hclass Stash{int size;//number of each spacesint quantity;//number of storage spacesint next;//Next empty space//Dynamically allocated array of bytes:unsigned char* storage;void inflate(int increase);public:void initialize(int size);void cleanup();int add(void* element);void* fetch(int index);int count();};#endif//STASH_H
注意到函数void inflate(int increase);被加入到了private里面,因为它只在add(入栈时发现空间不够用了才调用),所以不能被轻易访问,事实上它也确实不需要成为一个外部接口。


七、句柄类

先说一个实际的问题。对于一个公司的核心技术,技术管理人员可能不想所有人都能看到其代码,因此交给其他程序员使用的时候,可能是交给他们一个库文件,一个头文件。只要在头文件里能找到的接口,都可以调用。另一个事实是,当一个文件被修改,或它所依赖的头文件被修改,都需要重复编译该文件。这意味着程序员无论何时修改了一个类,无论修改的是公共接口的部分还是私有成员的声明部分,他都必须编译包含这个头文件的所有文件。这就是通常所说的易碎的基类问题(fragile base-class problem)对于一个大项目而言,这是非常耗时耗力的。
解决办法是----句柄类(handle class)。有关实现的任何东西都消失了,只剩一个单指针“smile"。改指针指向一个结构,该结构的定义与其所有的成员函数的定义一同出现在实现文件中。这样,只要接口部分不改变,头文件就不需要变动。儿实现部分可以任意更改,编译的时候只需编译单独地一个文件就OK。

#ifndef HANDLE_H#define HANDLE_Hclass Handle{struct Cheshire;Cheshire *smile;public:void initialize();void cleanup();int read();void change(int);};#endif
在头文件中并没有定义结构体Cheshire。只是声明了而已,但是这对于Cheshire类型的指针smile已经足够,编译器已经知道它是一个地址。

接下来你只需要在实现文件Handle.cpp里实现对结构Cheshire的定义即可。

#include<iostream>#include "Handle.h"using namespace std;struct Handle::Cheshire{int i;};void Handle::initialize(){smile = new Cheshire;smile->i = 0;}void Handle::cleanup(){delete smile;smile = NULL;}int Handle::read(){return smile->i;}void Handle::change(int i){smile->i = i;}int main(){Handle h;h.initialize();cout << "smile->i = " << h.read() << endl;h.change(5);cout << "smile->i = " << h.read() << endl;return 0;


0 0
原创粉丝点击