【问题标题】:How to make inherited class different from parent only by one value in C++?如何使继承的类与父类仅在 C++ 中的一个值不同?
【发布时间】:2018-01-29 18:00:27
【问题描述】:

我正在尝试为 UnitVector 编写一个类,已经为通用 Vector 编写了一个类。 UnitVector 类与 Vector 类的区别仅在于 abs 变量设置为 1.0f。我想知道解决这个问题的最佳方法是什么,是否最好创建另一个类 UnitVector,它继承 Vector 类(我目前的想法,这给我带来了问题)或者只是在 Vector 类中编写一个方法

这是我的Vector类代码:

Vector.h

class Vector
{
public:
    Vector();
    Vector(float x, float y);

    void set_by_angle(float abs, float angle);
    void set(float x, float y);

    void rotate(float angle);
    void scale(float scale_factor);
    void translate(float x, float y);
    void translate(Vector v);

    float get_abs();
    float get_angle();

    static Vector create_by_angle(float abs, float angle);
    static Vector create(float x, float y);
    static Vector create_from_vectors(Vector v1, Vector v2, float abs);
    static float get_distance(Vector v1, Vector v2);
    static float get_angle(float x, float y);
    static float get_angle(Vector v);

    void to_string();

    Vector operator=(const Vector &v);
    bool operator==(const Vector &v);
    bool operator!=(const Vector &v);
    Vector operator+=(const Vector &v);

    friend Vector operator+(const Vector &v1, const Vector &v2);
    friend Vector operator-(const Vector &v1, const Vector &v2);

    float x;
    float y;

private:
    float abs;
    float angle;
};

Vector.cpp

#define _USE_MATH_DEFINES
#include <math.h>
#include <iostream>
#include <string>

#include "vector.h"

using namespace std;

Vector::Vector() : Vector(0, 0) {}

Vector::Vector(float x, float y)
{
    set(x, y);
}

void Vector::set_by_angle(float abs, float angle)
{
    this->abs = abs;
    this->angle = angle;

    x = abs * cos(angle);
    y = abs * sin(angle);
}

void Vector::set(float x, float y)
{
    this->x = x;
    this->y = y;

    abs = get_abs();
    angle = get_angle();
}

void Vector::rotate(float angle)
{
    set_by_angle(this->abs, this->angle + angle);
}

void Vector::scale(float scale_factor)
{
    set(x * scale_factor, y * scale_factor);
}

void Vector::translate(float x, float y)
{
    set(this->x + x, this->y + y);
}

void Vector::translate(Vector v)
{
    translate(v.x, v.y);
}

float Vector::get_abs()
{
    return sqrt(pow(x, 2) + pow(y, 2));
}

float Vector::get_angle()
{
    return get_angle(x, y);
}

Vector Vector::create_by_angle(float abs, float angle)
{
    Vector v;
    v.set_by_angle(abs, angle);

    return v;
}

Vector Vector::create(float x, float y)
{
    Vector v;
    v.set(x, y);

    return v;
}

float Vector::get_distance(Vector v1, Vector v2)
{
    return sqrt(pow(v1.x - v2.x, 2) + pow(v1.y - v2.y, 2));
}

Vector Vector::create_from_vectors(Vector v1, Vector v2, float abs)
{
    float x = v2.x - v1.x;
    float y = v2.y - v1.y;

    Vector v;
    v.set_by_angle(abs, Vector(x, y).get_angle());

    return v;
}

float Vector::get_angle(float x, float y)
{
    float tan = 0.0f;
    float angle = 0.0f;

    if (x != 0)
    {
        tan = y / x;
        angle = atan(tan);

        // this setting applies to the graphic reference system
        if (x > 0 && y < 0) angle = 2 * M_PI + angle;
        if (x < 0 && y > 0) angle += M_PI;
        if (x < 0 && y < 0) angle += M_PI;
    }
    if (x == 0)
    {
        if (y > 0) angle = M_PI_2;
        if (y < 0) angle = 3 * M_PI_2;
    }
    if (y == 0)
    {
        if (x > 0) angle = 0.0f;
        if (x < 0) angle = M_PI;
    }

    return angle;
}

float Vector::get_angle(Vector v)
{
    return get_angle(v.x, v.y);
}

void Vector::to_string()
{
    cout << "x: " + std::to_string(x) + " y: " + std::to_string(y) << endl;
}

Vector operator+(const Vector &v1, const Vector &v2)
{
    Vector tmp;

    tmp.set(v1.x + v2.x, v1.y + v2.y);

    return tmp;
}

Vector operator-(const Vector &v1, const Vector &v2)
{
    return v1 + Vector(-v2.x, -v2.y);
}

Vector Vector::operator+=(const Vector &v)
{
    set(x + v.x, y + v.y);

    return *this;
}

Vector Vector::operator=(const Vector &v)
{
    set(v.x, v.y);

    return *this;
}

bool Vector::operator==(const Vector &v)
{
    return
    (
        (x == v.x)
        &&
        (y == v.y)
    );
}

bool Vector::operator!=(const Vector &v)
{
    return !(*this == v);
}

提前致谢!

【问题讨论】:

  • 为什么要声明一个新类?只需提供Vector::normalize() 即可完成
  • 如果你有一个Vector 一个UnitVector你会有Vectors有单位长度但不是UnitVector...你不会得到任何好处,但有很多困惑
  • 这是旧的"Is a square a rectangle?" 问题。您希望能够为Vector 独立设置xy。既然你不能为UnitVector 这样做,那么它就不是Vector。它只是与一个非常相似。
  • 我最近在一个类似的问题上提到了这一点,但我不记得它是否是同一个 OP,所以如果我重复自己,但有一个名为 Vector 的类,我深表歉意使用std 的代码是个坏主意。希望您至少将 Vector 放在自己的命名空间中。 CVectorPlotting::VectorPlottingVectorVector_t

标签: c++ inheritance


【解决方案1】:

只需添加以下两个方法:

void normalize()
{
    float scalar = 1.0 / this->get_abs();

    this->x *= scalar;
    this->y *= scalar;
}

还有:

static Vector get_unit(const Vector &v)
{
    float scalar = 1.0 / v.get_abs();

    return Vector(v.x * scalar, v.y * scalar);
}

【讨论】:

  • 我会把它写成 one 方法,Vector Vector::normalise() const
  • 我个人认为使用normalizeconst 方法会产生误导。但这只是我个人的喜好,我猜。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-06-05
  • 2015-03-14
  • 1970-01-01
  • 1970-01-01
  • 2013-04-07
  • 2014-06-20
  • 1970-01-01
相关资源
最近更新 更多