C++的存取控制
public:在其后声明的所有成员对所有的人都可以存取
private:除了该类型的创建者和类的内部成员函数之外,任何人都不能存取这些成员。
protected: protected与private基本相似,只有一点不同:继承的结构可以访问protected成员,但不能访问p r ivat e成员。
友元
如果程序员想允许不属于当前结构的一个成员函数存取结构中的数据,那么可以在struct内部声明这个函数为友元。
可以把一个全局函数声明为友元,也可以把另一个struct中的成员函数甚至整个struct都声明为友元。
// Declaration (incomplete type specification):
struct X;
struct Y
{
void f(X*);
};
struct X { // Definition
private:
int i;
public:
void initialize();
friend void g(X*, int); // Global friend
friend void Y::f(X*); // Struct member friend
friend struct Z; // Entire struct is a friend
friend void h();
};
void X::initialize() {
i = 0;
}
void g(X* x, int i) {
x->i = i;
}
void Y::f(X* x) {
x->i = 47;
}
struct Z {
private:
int j;
public:
void initialize();
void g(X* x);
};
void Z::initialize() {
j = 99;
}
void Z::g(X* x) {
x->i += j;
}
void h() {
X x;
x.i = 100; // Direct data manipulation
}
int main() {
X x;
Z z;
z.g(&x);
}
友元表明C++不是一个纯的面向对象的语言。友元函数是一个特权函数,是为了解决突发问题。
句柄类(handle classes)
C++中的存取控制允许将实现与接口部分分开,但实现的隐藏是不完全的。编译器必须知道一个对象的所有部分的声明,以便创建和管理它。
有时可能需要不让用户看到实现部分,就有必要把一个编译好的实际结构放在实现文件中,而不是让其暴露在头文件中。
当一个头文件被修改,依赖它的所有实现文件都需要被重新编译,如果只是修改实现部分,这就很没有必要。
解决这个问题的技术有时叫句柄类( handle classes)或叫“Cheshire Cat”。类的头文件中没有任何实现,只有一个指针“smile”,该指针指向一个结构,该结构的定义与其所有的成员函数的定义一样出现在实现文件中。这样,只要接口部分不改变,头文件就不需变动。而实现部分可以按需要任意更动,完成后只要对实现文件进行重新编译,然后再连接到项目中。
这里有个说明这一技术的简单例子。头文件中只包含公共的接口和一个简单的没有完全指定的类指针。
// Handle.h
// Handle classes
#ifndef HANDLE_H
#define HANDLE_H
class Handle {
struct Cheshire; // Class declaration only
Cheshire* smile;
public:
void initialize();
void cleanup();
int read();
void change(int);
};
#endif
// Handle.cpp {O}
// Handle implementation
#include "Handle.h"
#include "../require.h"
// Define Handle's implementation:
struct Handle::Cheshire {
int i;
};
void Handle::initialize() {
smile = new Cheshire;
smile->i = 0;
}
void Handle::cleanup() {
delete smile;
}
int Handle::read() {
return smile->i;
}
void Handle::change(int x) {
smile->i = x;
} ///:~