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
- 【初学】Objective-C学习笔记-Objectiv-C
- Mapx初学笔记(c#)
- Object C初学学习笔记(1)
- c++学习笔记(初学)
- c++学习笔记(初学)
- c初学笔记摘要
- 初学C#-----笔记一
- 初学C#-----笔记二
- 【初学】Objective-C学习笔记-委托代理(delegate)和协议(protocol)
- Cocos2d-x学习笔记(初学)
- SQL初学学习笔记(一)
- SQL初学学习笔记(二)
- LESS学习笔记(初学实用)
- Entity Framework学习笔记(初学)
- 初学Linux学习笔记
- 初学机器学习笔记
- 安卓学习笔记 1(初学笔记)
- Linux学习笔记 初学指南
- 音效单例类的实现和调用
- HDU 2962
- python学习——编写web框架
- An investigation into defense against SPIT
- 2016/8/8 [个人网站] 学习第八天
- c++学习笔记(初学)
- Python 列表解析课后
- [iOS][兼容性]iOS7 pushViewController,popViewControllerAnimated存在的问题
- 视图
- Android Studio com.android.dex.DexException: Multiple dex files define(重复引用包)
- 用Maven自动生成带有sh和bat启动脚本的java应用
- css伸缩布局盒flex属性 display:flex 详解
- 详解Android中AsyncTask的使用
- java常用设计模式