c++学习笔记(初学)

第 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::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为整数的范围。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

mypollyanna

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值