介绍操作符重载和友元的类设计
#ifndef VECTOR_H_
#define VECTOR_H_
#include <iostream>
namespace VECTOR
{
class Vector
{
private:
double x;
double y;
double mag;
double ang;
char mode;
void set_mag();
void set_ang();
void set_x();
void set_y();
public:
Vector();
Vector(double n1,double n2, char form = ' r ');
void set(double n1,double n2, char form = 'r');
~Vector();
double xval()const { return x; }//report x value
double yval()const { return y; }//report y value
double magval()const { return mag;}//report magnitude
double angval()const {return ang;}//report angle
void polar_mode(); //set mode to 'p'
void rect_mode(); //set mode to 'r'
Vector operator+ (const Vector & b) const;
Vector operator- (const Vector & c) 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);
};
}//end namespcae VECTOR
#endif
程序清单中的4个报告分量值的函数是在类声明中定义的,因此将自动成为内联函数。这些函数非常短,因此适于声明为内联函数。因为他们都不会修改对象数据,所以声明时使用了const限定符,这种句法用于声明那些不会对其显式访问的对象进行修改的函数。
下面的程序清单列出了上面的程序中声明的方法和友元函数的定义,该清单利用了名称空间的开放性,将方法定义添加到VECTOR名称空间中。请注意,构造函数和set()函数都设置了矢量的直角坐标和极坐标表示,因此需要这些值时,可直接使用而无需进行计算。另外,c++的内置数学函数在使用角度时以弧度为单位,所以函数在度和弧度之间进行行转换。该Vector类实现对用户隐藏了极坐标和直角坐标之间的转换以及弧度和度之间的转换等内容。用户只需知道:类在使用角度时以度为单位,可以使用两种等价的形式来表示矢量。
#include <cmath>
#include "vector.h"
using std::sin;
using std::cos;
using std::atan2;
using std::cout;
namespace VECTOR
{
const double Rad_to_deg = 57.2957795130823;
void Vector::set_mag()
{
mag = sqrt(x * x + y * y);
}
void Vector::set_ang()
{
if(x == 0 || y == 0)
ang = 0.0;
else ang = atan2 (y ,x);
}
//set x from polar coordinate
void Vector::set_x()
{
x = mag * cos (ang);
}
void Vector::set_y()
{
y = mag * sin (ang);
}
//public methods
Vector::Vector()
{
x = y = mag = ang = 0.0;
mode = 'r';
}
//construct vector from rectangular coordinates if form is r
// (the default) or else from polar coordinates if form is p
Vector::Vector(double n1, double n2, char form)
{
mode = form;
if( form == 'r')
{
x =n1;
y = n2;
set_mag();
set_ang();
}
else if(form == 'p')
{
mag = n1;
ang = n2 / Rad_to_deg;
set_x();
set_y();
}
else
{
cout << "Incorrect srd argument to Vector()--";
cout << "vector set to 0\n";
x = y = mag = ang = 0.0;
mode = 'r';
}
}
//set vector from rectangle coordinates if form is r
//(the default) or else from polar coordinates if form is p
void Vector::set (double n1, double n2 ,char form)
{
mode = form;
if(form == 'r')
{
x = n1;
y = n2;
set_mag();
set_ang();
}
else if(form == 'p')
{
mag = n1;
ang = n2 / Rad_to_deg;
set_x();
set_y();
}
else
{
cout << "Incorrect srd argument to Vector()--";
cout << "vector set to 0\n";
x = y = mag = ang =0.0;
mode = 'r';
}
}
Vector::~Vector()// sestructor
{
}
void Vector::polar_mode()
{
mode = 'p';
}
void Vector::rect_mode()
{
mode = 'r';
}
// operator overloading
// add two vectors
Vector Vector::operator+ (const Vector & b)const
{
return Vector (x + b.x,y + b.y);
}
//substract Vector b from a
Vector Vector::operator- (const Vector & b)const
{
return Vector(x-b.x,y-b.y);
}
//reverse sign of Vector
Vector Vector::operator- ()const
{
return Vector(-x, -y);
}
//multiple vector by n
Vector Vector::operator* (double n)const
{
return Vector (n * x, n * y);
}
//friend methods
//multiple n by vector a
Vector operator* (double n, const Vector & a)
{
return a * n;//convert double times Vector to Vector times double
}//这样的话,就可以直接使用上面那个函数定义的重载的乘法。
//display rectangle coordinates if mode is r,
// else display polar coordinates if mode is p
std::ostream & operator<< (std::ostream & os, const Vector & v)
{
if(v.mode == 'r')
os << "(x, y) = (" << v.x <<","<< v.y << ")";
else if(v.mode== 'p')
{
os << " (m,a) = (" << v.mag << ", " << v.ang*Rad_to_deg<<")";
}
else
os << "Vector object mode is invalid ";
return os;
}
}// end namespace VECTOR