既然友元具有访问权限,那么当把一个成员函数声明成友元的时候,我们必须要指明该成员函数属于哪个类:
class Screen {
// Window_mgr::clear必须在Screen类之前被声明
friend void Window_mgr::clear(ScreenIndex);
// Screen类的剩余部分
};
想要令某个成员函数作为友元,我们必须仔细组织结构。首先定义类,其中声明clear函数,但不能定义。在clear使用Screen的成员之前必须先声明Screen。接下来定义Screen,包括对clear的友元声明。最后定义clear,此时它可以使用Screen的成员。
重载函数在声明成友元的过程中,需要对函数中的每一个分别进行声明:
extern std::ostream& storeOn(std::ostream &, Screen &);
extern BitMap& storeOn (BitMap &, Screen &);
class Screen {
// storeOn的ostream版本能访问Screen对象的私有部分
friend std::ostream& storeOn(std::ostream &, Screen &);
};
未被声明之前,友元的类的成员无法调用该友元函数:
struct X {
friend void f() { /* 友元函数可以定义在类的内部*/ }
x() { f(); } // 错误:f尚未被声明
void g();
void h();
};
void X::g() { return f(); }//错误:f未被声明
void f(); //声明定义在X中的函数
void X::h() { return f(); }//正确:f已被声明
类的作用域:
每个类具有自己的作用域。在作用域之外,普通的数据和函数成员只能由对象、引用或者指针使用成员访问运算符来访问。对于类类型的成员则使用作用域运算符来访问。不论哪种情况,运算符之后的名字必须是对应类的成员:
Screen::pos ht = 24, wd = 80; //使用Screen定义的pos类型
Screen scr(ht, wd, ' ');
Screen *p = &scr;
char c = scr.get(); //访问scr对象的get成员
c = p->get(); //访问p所指对象的get成员
void Window_mgr::clear(ScreenIndex i)
{
Screen &s = screens[i];
s.contents = string(s.height * s.width, ' ');
}
函数的返回类型通常出现在函数名之前。因此当成员函数定义在类的外部时,返回类型中使用的名字都位于类的作用域之外。我们可以向Window_mgr类中添加一个新的名为addScreen的函数,它负责向显示器添加一个新的屏幕。这个成员的返回类型将是ScreenIndex, 用户可以通过它定义到指定Screen:
class Window_mgr {
public:
//向窗口添加一个Screen, 返回它的编号
ScreenIndex addScreen(const Screen&);
// 其他成员与之前的版本一样
};
//首先处理返回类型,之后我们才进入Window_mgr的作用域
Window_mgr::ScreenIndex
Window_mgr::addScreen(const Screen &s)
{
screens.push_back(s);
return screens.size() - 1;
}
版权声明:本文为MDeleter原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。