您的位置:首页 > 编程语言 > C语言/C++

c++学习笔记(初学)

2016-08-08 12:40 204 查看

第 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);
注意:
① 不能用成员运算符来调用;
② 不是成员函数但与成员函数的访问权限相同;
③ 函数定义不要使用解析运算符::;

4000
④ 不要在定义中使用关键字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::RECT				os << "(x,y) = (" << v.x << "," << v.y << ")");
else if(v.mode == Vector::POL)
{
os << "(m,a) = (" << v.mag << "," << v.ang * Rad_to_deg << ")";
}
else
os << "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为整数的范围。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: