广州房产网站长工具seo综合查询问题
广州房产网,站长工具seo综合查询问题,一建分为哪几个专业,龙泉建设局网站友元
您知道#xff0c;C控制对类对象私有部分的访问。通常#xff0c;公有类方法提供唯一的访问途径#xff0c;但是有时候这种限制太严格#xff0c;以致于不适合特定的编程问题。在这种情况下#xff0c;C提供了另外一种形式的访问权限#xff1a;友
元。友元有3 种将被转换为下面的成员函数调用AB.operator*(2.75);但下面的语句又如何呢A2.75*B;从概念上说2.75 * B 应与B *2.75 相同但第一个表达式不对应于成员函数因为2.75 不是Time 类型的对象。记住左侧的操作数应是调用对象但2.75 不是对象。因此编译器不能使用成员函数调用来替换该表达式。解决这个难题的一种方式是告知每个人包括程序员自己只能按B * 2.75 这种格式编写不能写成2.75 * B。这是一种对服务器友好-客户警惕的server-friendly, client-beware解决方案与OOP 无关。然而还有另一种解决方式——非成员函数记住大多数运算符都可以通过成员或非成员函数来重载。非成员函数不是由对象调用的它使用的所有值包括对象都是显式参数。这样编译器能够将下面的表达式A2.75*B;与下面的非成员函数调用匹配Aoperator*(2.75,B);该函数的原型如下Time operator*(double m,const Time t);对于非成员重载运算符函数来说运算符表达式左边的操作数对应于运算符函数的第一个参数运算符表达式右边的操作数对应于运算符函数的第二个参数。而原来的成员函数则按相反的顺序处理操作数也就是说double 值乘以Time 值。使用非成员函数可以按所需的顺序获得操作数先是double然后是Time但引发了一个新问题非成员函数不能直接访问类的私有数据至少常规非成员函数不能访问。然而有一类特殊的非成员函数可以访问类的私有成员它们被称为友元函数。创建友元创建友元函数的第一步是将其原型放在类声明中并在原型声明前加上关键字friendfriend Time operator*(double m,const Time t);该原型意味着下面两点虽然operator *( )函数是在类声明中声明的但它不是成员函数因此不能使用成员运算符来调用虽然operator *( )函数不是成员函数但它与成员函数的访问权限相同。第二步是编写函数定义。因为它不是成员函数所以不要使用Time::限定符。另外不要在定义中使用关键字friend定义应该如下Time operator*(double m,const Time t) { Time result; long totalminutest.hoours*mult*60t.minutes*mult; result.hourstotalminutes/60; result.minutestotalminutes%60; return result; }有了上述声明和定义后下面的语句A2.75*B;将转换为如下语句从而调用刚才定义的非成员友元函数Aoperator*(2.75,B);总之类的友元函数是非成员函数其访问权限与成员函数相同。实际上按下面的方式对定义进行修改交换乘法操作数的顺序可以将这个友元函数编写为非友元函数Time operator*(double m,const Time t) { return t*m; }原来的版本显式地访问t.minutes 和t.hours所以它必须是友元。这个版本将Time 对象t 作为一个整体使用让成员函数来处理私有值因此不必是友元。然而将该版本作为友元也是一个好主意。最重要的是它将该作为正式类接口的组成部分。其次如果以后发现需要函数直接访问私有数据则只要修改函数定义即可而不必修改类原型。提示如果要为类重载运算符并将非类的项作为其第一个操作数则可以用友元函数来反转操作数的顺序。常用的友元重载运算符一个很有用的类特性是可以对运算符进行重载使之能与cout 一起来显示对象的内容。与前面介绍的示例相比这种重载要复杂些因此我们分两步而不是一步来完成。假设trip 是一个Time 对象。为显示Time 的值前面使用的是Show( )。然而如果可以像下面这样操作将更好couttrip;之所以可以这样做是因为是可被重载的C运算符之一。实际上它已经被重载很多次了。最初运算符是C 和C的位运算符将值中的位左移参见附录E。ostream 类对该运算符进行了重载将其转换为一个输出工具。前面讲过cout 是一个ostream 对象它是智能的能够识别所有的C基本类型。这是因为对于每种基本类型ostream 类声明中都包含了相应的重载的operator( )定义。也就是说一个定义使用int 参数一个定义使用double 参数等等。因此要使cout 能够识别Time 对象一种方法是将一个新的函数运算符定义添加到ostream 类声明中。但修改iostream 文件是个危险的主意这样做会在标准接口上浪费时间。相反通过Time 类声明来让Time 类知道如何使用cout。1的第一种重载版本要使Time 类知道使用cout必须使用友元函数。这是什么原因呢因为下面这样的语句使用两个对象其中第一个是ostream 类对象coutcouttrip;如果使用一个Time 成员函数来重载Time 对象将是第一个操作数就像使用成员函数重载*运算符那样。这意味着必须这样使用tripcout;这样会令人迷惑。但通过使用友元函数可以像下面这样重载运算符void operator(ostream os,const Time t) { ost.hourshours,t.minutesminutes; }这样可以使用下面的语句couttrip;按下面这样的格式打印数据4 hours,23 minutes注意新的operator( )定义使用ostream 引用os 作为它的第一个参数。通常情况下os 引用cout 对象如表达式cout trip 所示。但也可以将这个运算符用于其他ostream 对象在这种情况下os 将引用相应的对象。调用cout trip 应使用cout 对象本身而不是它的拷贝因此该函数按引用而不是按值来传递该对象。这样表达式cout trip 将导致os 成为cout 的一个别名而表达式cerr trip 将导致os 成为cerr的一个别名。Time 对象可以按值或按引用来传递因为这两种形式都使函数能够使用对象的值。按引用传递使用的内存和时间都比按值传递少。2的第二种重载版本前面介绍的实现存在一个问题。像下面这样的语句可以正常工作couttrip;但这种实现不允许像通常那样将重新定义的运算符与cout 一起使用coutTrip time:trip(Tuesday)\n;要理解这样做不可行的原因以及必须如何做才能使其可行首先需要了解关于cout 操作的一点知识。请看下面的语句int x5; int y8; coutxy;C从左至右读取输出语句意味着它等同于(coutx)y;正如iosream 中定义的那样运算符要求左边是一个ostream 对象。显然因为cout 是ostream 对象所以表达式cout x 满足这种要求。然而因为表达式cout x 位于 y 的左侧所以输出语句也要求该表达式是一个ostream 类型的对象。因此ostream 类将operator( )函数实现为返回一个指向ostream 对象的引用。具体地说它返回一个指向调用对象这里是cout的引用。因此表达式(cout x)本身就是ostream 对象cout从而可以位于运算符的左侧。可以对友元函数采用相同的方法。只要修改operator( )函数让它返回ostream 对象的引用即可ostream operator(ostream os,const Time t) { ost.hourshours,t.minutesminutes; return os; }注意返回类型是ostream 。这意味着该函数返回ostream 对象的引用。因为函数开始执行时程序传递了一个对象引用给它这样做的最终结果是函数的返回值就是传递给它的对象。也就是说下面的语句couttrip;将被转换为下面的调用operator(cout,trip);而该调用返回cout 对象。因此下面的语句可以正常工作coutTrip time:trip(Tuesday)\n;我们将这条语句分成多步来看看它是如何工作的。首先下面的代码调用ostream 中的定义它显示字符串并返回cout 对象couttrip(Tuesday)\n;接下来程序使用的Time 声明显示trip 值并再次返回cout 对象。这将语句简化为cout(Tudesday)\n;现在程序使用ostream 中用于字符串的定义来显示最后一个字符串并结束运行。有趣的是这个operator( )版本还可用于将输出写入到文件中#includefstream ... ofstream fout; fout.open(savetime.txt) Time trip(12,40); fouttrip;其中最后一条语句将被转换为这样operator(fout,trip);另外正如第8 章指出的类继承属性让ostream 引用能够指向ostream 对象和ofstream 对象。提示一般来说要重载运算符来显示c_name 的对象可使用一个友元函数其定义如下ostream operator(ostream os,const c_name obj) { os...; return os; }程序清单11.10 列出了修改后的类定义其中包括operator*( )和operator( )这两个友元函数。它将第一个友元函数作为内联函数因为其代码很短。当定义同时也是原型时就像这个例子中那样要使用friend 前缀。警告只有在类声明中的原型中才能使用friend 关键字。除非函数定义也是原型否则不能在函数定义中使用该关键字。#ifndef MYTIME3_H_ #define MYTIME3_H_ #include iostream class Time { private: int hours; int minutes; public: Time(); Time(int h, int m 0); void AddMin(int m); void AddHr(int h); void Reset(int h 0, int m 0); Time operator(const Time t) const; Time operator-(const Time t)const; Time operator*(double n) const; friend Time operator*(double m, const Time t) { return t * m; } friend std::ostream operator(std::ostream os, const Time t); }; #endif程 序清单11.11 mytime3.cpp#include mytime3.h Time::Time() { hours minutes 0; } Time::Time(int h, int m) { hours h; minutes m; } void Time::AddMin(int m) { minutes m; hours minutes / 60; minutes % 60; } void Time::AddHr(int h) { hours h; } void Time::Reset(int h, int m) { hours h; minutes m; } Time Time::operator(const Time t) const { Time sum; sum.minutes minutes t.minutes; sum.hours hours t.hours sum.minutes / 60; sum.minutes % 60; return sum; } Time Time::operator-(const Time t) const { Time sum; sum.minutes minutes - t.minutes; sum.hours hours t.hours sum.minutes / 60; sum.minutes % 60; return sum; } Time Time::operator-(const Time t) const { Time diff; int tot1, tot2; tot1 t.minutes 60 * t.hours; tot2 minutes 60 * hours; diff.minutes (tot2 - tot1) % 60; diff.hours (tot2 - tot1) / 60; return diff; } Time Time::operator*(double mult)const { Time result; long totalminutes hours * mult * 60 minutes * mult; result.hours totalminutes / 60; result.minutes totalminutes % 60; return result; } std::ostream operator(std::ostream os, const Time t) { os t.hours hours, t.minutes minutes; return os; }程序清单11.12 是一个示例程序。从技术上说在usetime3.cpp 中不必包含头文件iostream因为在mytime3.h 中已经包含了该文件。然而作为Time 类的用户您并不知道在类代码文件中已经包含了哪些文件因此您应负责将您编写的代码所需的头文件包含进来。#include iostream #includemytime3.h int main() { using std::cout; using std::endl; Time aida(3, 35); Time tosca(2, 48); Time temp; cout Aida and Tosca:\n; cout aida ; tosca endl; temp aida tosca; cout Aida Tosca: temp endl; temp aida * 1.17; cout Aida*1.17: temp endl; cout 10.0 * Tosca: 10.0 * tosca endl; return 0; }输出结果Aida and Tosca: 3hours,35minutes;2hours,48minutes Aida Tosca:6hours,23minutes Aida*1.17:4hours,11minutes 10.0 * Tosca:28hours,0minutes