一、友元函数
友元函数是定义在类外的普通函数,但是可以访问类的所有成员,包括私有和保护成员。
它不是类的成员函数,但是要在类里声明。
例子:
class A
{
// 友元函数可以在类中任何地方声明,不受访问限定符限制
friend void print();
public:
...
private:
int a;
int b;
int c;
};
// 友元函数是定义在类外的普通函数
// 但是可以访问类的私有和保护成员
void print()
{
cout << a << ' ' << b << ' ' << c << endl;
}
注意,一个函数可以是多个类的友元函数,只要在每个类中声明友元函数即可。
二、友元类
如果 A 是 B 的友元类,则在 A 中可以访问 B 的所有成员,包括私有和保护成员。
前提是要在 B 里声明 A 是 B 的友元类。声明方式与友元函数类似,可以在类中任何地方声明,不受访问限定符限制。
例子:
class B
{
// 友元类可以在类中任何地方声明,不受访问限定符限制
friend class A;
public:
...
private:
int x;
int y;
int z;
};
class A
{
public:
// 声明了友元类,在 A中就可以访问 B的私有和保护成员
void func(B& d)
{
d.x = 1;
d.y = 2;
...
}
private:
...
};
注意,友元关系是单向的,而且不能传递、不能继承。
单向:比如上面的例子中,A 是 B 的友元类,但是 B 不是 A 的友元类,B 中不能访问 A 的非公有成员,除非也在 A 中声明 B 是 A 的友元类。
不能传递:比如 A 是 B 的友元类,B 是 C 的友元类,但是不能推出 A 是 C 的友元类。
不能继承:to be continued…
三、内部类
在一个类里声明的另一个类,叫作内部类。
内部类可以访问外部类的所有成员,包括私有成员和保护成员。但是外部类不能访问内部类的非公有成员。
例子:
class A
{
public:
// B是 A的内部类
class B
{
public:
// B中可以访问 A的所有成员
void func(A& d)
{
d.x = 1;
d.y = 0;
}
};
private:
int x;
int y;
};
事实上,内部类就是外部类的友元类,它们是两个独立的类。
但是创建内部类的对象时,需要这样表示:外部类名::内部类名 对象名
例子:
class OuterClass
{
public:
class InnerClass
{
public:
void display()
{
cout << "Inner Class" << endl;
}
};
};
int main()
{
OuterClass::InnerClass innerObj;//创建内部类的对象
innerObj.display();
return 0;
}
内部类可以在外部类的任意位置声明,但是与友元类声明不同的是,内部类会受访问限定符的限制。
四、小结
友元提供了一种突破封装的方式,有时可以提供便利。
但是友元会增加类与类之间的耦合度,不宜多用。