c++学习笔记(初学)

来源:互联网 发布:js点击函数 编辑:程序博客网 时间:2024/06/06 15:04

第 11 章  使用类

一、运算符重载

旨在让我们能够用同名的函数来完成相同的基本操作。
例如,在一个计算时间的类中,我们定义了一个计算时间和的函数:
Time Time::Sum(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 total;
total = coding.Sum(fixing);   //其中coding和fixing是Time的两个已赋值对象
这时,我们可以将Time类转换为重载的加法运算符:
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;}
这时,我们就可以使用运算符表示法:total = coding + fixing;
或者也可以total = coding.operator+(fixing);
注意,运算符左侧的对象是调用对象,右边的对象是作为参数被传递的对象。

二、友元

由上一小节可知,重载运算符后,运算符左侧的对象是调用对象,右边的对象是作为参数被传递的对象。但如果有以下语句:A = 2.75 * B;将会编译错误。而我们知道,非成员函数不是由对象调用的,它使用的所有值都是显示参数。故我们通过让非成员函数成为类的友元,可以赋予该函数与类的成员函数相同的访问权限。
函数实例如下:
friend Time operator*(double m, const Time & t);
注意:
① 不能用成员运算符来调用;
② 不是成员函数但与成员函数的访问权限相同;
③ 函数定义不要使用解析运算符::;
④ 不要在定义中使用关键字friend。

重载<<运算符
1、要使Time类知道使用cout,必须使用友元函数:
void operator<<(ostream & os, const Time & t){   os << t.hours << " hours, " << t.minutes << " minutes";}
这样可以使用这样的语句:cout << trip;
2、然而,倘若要使cout << "Trip time: " << trip << " (Tuesday)\n"情况允许,则只要修改operator<<()函数,让它返回ostream对象的引用即可:
ostream & operator<<(ostream & os, const Time & t){   os << t.hours << " hours, " << t.minutes << " minutes";   return os;}

三、类的实例(矢量类)
使用了类的重载和友元的类设计
#ifndef VECTOR_H_#define VECTOR_H_#include<iostream>namespace VECTOR    //将类声明放在VECTOR名称空间中{   class Vector   {        public:        enum Mode {RECT, POL};//用于标识两种表示法 直角坐标和极坐标 private:double x;double y;double mag;double ang;Mode mode;void set_mag();void set_ang();void set_x();void set_y();public:Vector();Vector(double n1,double n2,Mode form = RECT);void reset(double n1,double n2,Mode form = RECT);~Vector();//声明不会对其显示访问的对象进行修改的函数用const限定符 double xval() const {return x;}double yval() const {return y;}double magval() const {return mag;}double angval() const {return ang;}//将自动成为内联函数 void polar_mode();void rect_mode();Vector operator+(const Vector & b) const;Vector operator-(const Vector & b) const;Vector operator-() const;Vector operator*(double n) const;friend Vector operator*(double n,const Vector & a);friend std::ostream & operator<<(std::ostream & os,const Vector & v);   } }#endif
实现:
#include<cmath>#include "vect.h"using std::sqrt;using std::sin;using std::cos;using std::atan;using std::atan2;using std::cout;namespace VECTOR{const double Rad_to_deg = 45.0 / atan(1.0);//约为57.2957795 void Vector::set_mag(){mag = sqrt(x * x + y * y);}void Vector::set_ang(){if(x == 0.0 && y == 0.0)ang = atan2(y,x);}//已知极坐标求直角坐标 void Vector::set_x(){x = mag * cos(ang); }void Vector::set_y(){y = mag * sin(ang);}Vector::Vector(){x = y = mag = 0.0;mode = RECT;}Vector(double n1,double n2,Mode form){mode = form;if(form == RECT){x = n1;y = n2;set_mag();set_ang();}else if (form = POL){mag = n1;ang = n2 / Rad_to_deg;set_x();set_y();}else{cout << "Incorrect 3rd argument to Vector() -- ";cout << "vector set to 0\n";x = y = mag = ang = 0.0;mode = RECT;}}void reset(double n1,double n2,Mode form){mode = form;if(form = RECT){x = n1;y = n2;set_mag();set_ang();}else if(form = POL){mag = n1;ang = n2 / Rad_to_deg;set_x();set_y();}else{cout << "Incorrect 3rd argument to Vector() -- ";cout << "vector set to 0\n";x = y = mag = ang = 0.0;mode = RECT;}}Vector::~Vector(){}void Vector::polar_mode(){mode = POL;}void Vector::rect_mode(){mode = RECT;}Vector Vector::operator+(const Vector & b) const{return Vector(x + b.x, y + b.y);}//将新的x和y分量传递给构造函数,而后者将使用这些值来创建无名的新对象,并返回该对象的副本Vector Vector::operator-(const Vector & b) const{return Vector(x - b.x, y - b.y);}Vector Vector::operator-() const  //返回与原来矢量相反的矢量{return Vector(-x,-y);}Vector Vector::operator*(double n) const{return Vector(n * x,n * y);}Vector operator*(double n,const Vector & a){return a * n;}std::ostream & operator<<(std::ostream & os,const Vector & v){if(v.mode == Vector::RECT) //因为友元函数不在类作用域内,因此必须使用Vector::RECT,但这个友元函数在名称空间VECTOR中,因此无需使用全限定名VECTOR::Vector::RECTos << "(x,y) = (" << v.x << "," << v.y << ")");else if(v.mode == Vector::POL){os << "(m,a) = (" << v.mag << "," << v.ang * Rad_to_deg << ")";}elseos << "Vector object mode is invalid";return os;}}

ps:随机数的生成
stdlib头文件下的srand()和rand()函数
我们知道,rand()函数可以产生随机数,但这是一个伪随机数,每次执行时都是相同的。若要不同,则需要用srand()函数来设置rand()产生随机数时的随机种子,当用户未设定随机种子时,系统默认的随机种子为1。而我们知道,我们每一次运行程序的时间是不同的,故可以使用time(0)的返回值来设置种子,即srand(time(0))。其中头文件ctime包含了time()的原型。
产生一定范围随机数的通用表达式
a + rand() % n,其中a为起始值,n为整数的范围。
1 0