先前回顾
在【C++进阶】 遵循TDD原则,实现平面向量类(Vec2D)中我们初步实现了Vec2D内容,现在做出一定的改进:
实现Vec2D的一半二元算数运算符重载
1、 + - (两个Vec2D对象运算以及1个Vec2D对象与一个double数运算)
2、*(点乘和数乘)
同时将之前涉及对象拷贝的函数用传引用的方式进行修改。
注意,若有对象拷贝则需要传引用,如果只是简单的值拷贝,则不需要传引用。
知识点
先看看我们一般是怎么调用二元运算符:
注意最后一个是个“错误”的写法,因为这个不属于成员函数的写法,z不是Vec2D类的对象。
但是常识告诉我们,这样写和d的写法应该是一样的。
Vec2D a{1,2}, b{3, 6}; double z {1.3};
Vec2D c = a + b; // a.operator+(b); à Vec2D Vec2D::operator+(Vec2D);
Vec2D d = a + z; // a.operator+(z); à Vec2D Vec2D::operator+(double);
Vec2D e = z + b; // z.operator+(b); à Vec2D double::operator+(Vec2D); 错误!
下面是这几个重载函数的原型,注意最后一个是个友元函数,关于友元函数记不清的
struct Vec2D {
Vec2D operator +(Vec2D); //成员函数
Vec2D operator +(double); //成员函数
friend Vec2D operator +(double, Vec2D); //非成员(友元)函数
};
Vec2D operator +(double, Vec2D) { // Do something
}
修改部分
1、首先完善h文件
class Vec2D
{
private:
double x_;
double y_;
public:
Vec2D();
Vec2D(double , double );
~Vec2D();
// 将向量转换为字符串表达形式
std::string toString();
// 向量加法
Vec2D add(const Vec2D& secondVec2D);
//与数值相加
Vec2D add(double num);
//加法函数的重载
Vec2D operator +(const Vec2D& secondVec2D);
Vec2D operator +(const double num);
// 读取或修改向量元素
double& at(const int index);
// 向量减法
Vec2D subtract(const Vec2D& secondVec2D);
//与数值相减
Vec2D subtract(const double num);
//减法函数的重载
Vec2D operator -(const Vec2D& secondVec2D);
Vec2D operator -(const double num);
// 向量点积
double dot(const Vec2D& secondVec2D);
// 向量数乘
Vec2D multiply(const double multiplier);
//向量乘法的重载
double operator *(const Vec2D& secondVec2D);
Vec2D operator *(const double multiplier);
//补充一个乘法友元函数
friend Vec2D operator *(const double multiplier,Vec2D vec2d);
// 向量求负值
Vec2D negative();
// 向量自增1
Vec2D& increase();
// 向量自减1
Vec2D& decrease();
// 求向量的范数(长度)
double magnitude();
// 求Vec2D与x+轴的夹角
double direction();
// 比较两个向量的长度。如果firstVec2D小于secondVec2D,返回-1,若大于则返回1,若相等则返回0
int compareTo(Vec2D secondVec2D);
};
2、在cpp文件中补充函数的具体细节
Vec2D::Vec2D() {
x_ = 0.0;
y_ = 0.0;
}
Vec2D::Vec2D(double x, double y) {
x_ = x;
y_ = y;
}
Vec2D::~Vec2D() {
}
// 将向量转换为字符串表达形式
std::string Vec2D::toString()
{
// TODO: 在此处添加实现代码.
return std::string("(" + std::to_string(x_) + ", "+ std::to_string(y_) + ")");
}
// 向量加法
Vec2D Vec2D::add(const Vec2D& secondVec2D)
{
// TODO: 在此处添加实现代码.
return Vec2D(x_ + secondVec2D.x_ , y_ + secondVec2D.y_);
}
//与数值相加
Vec2D Vec2D::add(double num)
{
// TODO: 在此处添加实现代码.
return Vec2D(this->x_ + num , this->y_ + num);
}
//加法重载函数
Vec2D Vec2D::operator +(const Vec2D& secondVec2D)
{
return this->add(secondVec2D);
}
Vec2D Vec2D::operator +(const double num)
{
return this->add(num);
}
// 向量减法
Vec2D Vec2D::subtract(const Vec2D& secondVec2D)
{
// TODO: 在此处添加实现代码.
return Vec2D(x_ - secondVec2D.x_ , y_ - secondVec2D.y_);
}
// 向量减数
Vec2D Vec2D::subtract(const double num)
{
// TODO: 在此处添加实现代码.
return Vec2D(this->x_ - num , this->y_ - num);
}
//减法重载函数
Vec2D Vec2D::operator -(const Vec2D& secondVec2D)
{
return this->subtract(secondVec2D);
}
Vec2D Vec2D::operator -(const double num)
{
return this->subtract(num);
}
// 向量点积
double Vec2D::dot(const Vec2D& secondVec2D)
{
// TODO: 在此处添加实现代码.
return (x_ * secondVec2D.x_ + y_ * secondVec2D.y_);
}
// 向量数乘
Vec2D Vec2D::multiply(const double multiplier)
{
// TODO: 在此处添加实现代码.
return Vec2D(x_ * multiplier ,y_ * multiplier);
}
//乘法重载函数
Vec2D Vec2D::operator *(const double num)
{
return this->multiply(num);
}
double Vec2D::operator *(const Vec2D& secondVec2D)
{
return this->dot(secondVec2D);
}
//乘法友元函数,不是Vec2D的成员函数
Vec2D operator *(const double multiplier,Vec2D vec2d)
{
return vec2d.multiply(multiplier);
}
// 向量求负值
Vec2D Vec2D::negative()
{
// TODO: 在此处添加实现代码.
return Vec2D( -x_ , -y_);
}
// 向量自增1
Vec2D& Vec2D::increase()
{
x_++;
y_++;
// TODO: 在此处添加实现代码.
return (*this);
}
// 向量自减1
Vec2D& Vec2D::decrease()
{
x_--;
y_--;
// TODO: 在此处添加实现代码.
return (*this);
}
// 求向量的范数(长度)
double Vec2D::magnitude()
{
// TODO: 在此处添加实现代码.
return sqrt(x_ * x_ + y_ * y_);
}
// 求Vec2D与x+轴的夹角
double Vec2D::direction()
{
// TODO: 在此处添加实现代码.
return atan(y_ / x_);
}
// 比较两个向量的长度。如果firstVec2D小于secondVec2D,返回-1,若大于则返回1,若相等则返回0
int Vec2D::compareTo(Vec2D secondVec2D)
{
// TODO: 在此处添加实现代码.
double m1 = this->magnitude();
double m2 = secondVec2D.magnitude();
if(abs(m1 - m2) < 1e-10)
return 0;
else
return (m1 > m2 ? 1 : -1);
}
// 读取或修改向量元素
double& Vec2D::at(const int index)
{
if( 0 == index)
return x_;
else if(1 == index)
return y_;
//使用异常处理的方式,抛出异常,并且打印携带信息
else
throw std::out_of_range("at() only accept 1 or 2 as parameter");
// TODO: 在此处添加实现代码.
// TODO: 在此处插入 return 语句
}
3、运行测试函数
using std::cout;
using std::endl;
int main()
{
//创建向量对象
Vec2D v1{ 3,5 }, v2{ 4,6 };
//向量转为字符串
cout << "v1 = " << v1.toString() << endl;
cout << "v2 = " << v2.toString() << endl;
//向量加法: 向量 + 向量 ,向量 + 数
//Vec2D v3 = v1.add(v2);
//Vec2D v4 = v3.add(10.0);
//使用重载operator函数
Vec2D v3 = v1 + v2;
Vec2D v4 = v3 + 10.0;
cout << "v3 = " << v3.toString() << endl;
cout << "v4 = " << v4.toString() << endl;
//向量减法,向量点积,向量数乘
//Vec2D v5 = v2.subtract(v1);
//double v6 = v2.dot(v1); //两个向量的点积是一个数
//Vec2D v7 = v3.multiply(2.1);
//使用重载operator函数
Vec2D v5 = v2 - v1;
double v6 = v2 * v1; //两个向量的点积是一个数
Vec2D v7 = v3 * 2.1;
cout << "v2 - v1 = " << v5.toString() << endl;
cout << "v2 * v1 = " << v6 << endl;
cout << "v3 * 2.1 = " << v7.toString() << endl;
cout << "2.1 * v3 = " << (2.1 * v3).toString() << endl; //这里使用的是友元函数
//向量求负值
Vec2D v8 = v2.negative();
cout << "-v2 = " << v8.toString() << endl;
//向量自增/自减
cout << " ++v8 = " << v8.increase().toString() << endl;
cout << " --v2 = " << v2.decrease().toString() << endl;
//读取或者修改向量元素
cout << "v1.x_ = " << v1.at(0) << endl;
cout << "v1.y_ = " << v1.at(1) << endl;
//向量的长度magnitude 和角度direction
cout << "v1.magnitude = " << v1.magnitude() << endl;
cout << "v1.direction = " << v1.direction() << endl;
//比较两个向量
cout << "v1 compare v2 :" << v1.compareTo(v2) << endl;
return 0;
}
4、得到测试结果