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

第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_H

class Stash{
	int size;	//number of each spaces
	int quantity;	//number of storage spaces
	int 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_H

class 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;


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值