【问题标题】:use operator overload definition from base class in subclasses in C++在 C++ 的子类中使用基类中的运算符重载定义
【发布时间】:2021-10-12 11:08:57
【问题描述】:

我目前正在深入研究 C++。我有一个多态性/继承问题,我无法弄清楚,也没有找到(对我而言)似乎可以解决我的具体问题的在线答案:

我想要一个基类和几个派生子类。我想在子类访问的基类中定义通用函数/运算符重载,以避免代码重复。

这是我想弄清楚的例子:

class ElectricalUnit {
protected:
    float value;

public:
    ElectricalUnit(float _value) : value(_value) {};

    float getValue() const {
        return this->value;
    }

    // this should be the (only) place where the add operation for all subclasses is defined
    // note: I intentionally want to avoid changing the objects' state by returning a new object
    ElectricalUnit operator+ (const ElectricalUnit& other) const {
        return ElectricalUnit(this->value + other.getValue());
    }
};


class Voltage : public ElectricalUnit {
public:
    Voltage(float _voltage) : ElectricalUnit(_voltage) {};

    float getVoltage() const {
        return ElectricalUnit::getValue();
    }

    Voltage operator+ (const Voltage& other) {  // not having this function did not work
        // 1st try:
        return ElectricalUnit::operator+(other); // error: says no conversion is available??

        // 2nd try:
        return (Voltage)ElectricalUnit::operator+(other); // error: also says no conversion is available.

        // 3rd try (read it online)
        ElectricalUnit::operator+(other);
        return *this;  // does give wrong values, because the return value of operator+ is not used
    }
};


class Current : public ElectricalUnit {
    private:
    float current;

    public:
    Current(float current) : current(current) {};

    float getCurrent() { return this->current; };

    /* use operator+ method from base class --> but how? */
};

这里,VoltageCurrent 派生自基类 ElectricalUnit。在每个子类中添加电压或电流(或其他,如功率、能量等)都是相同的。所以在ElectricalUnit 中我定义了运算符重载方法,并希望子类使用这个方法。在考虑公差等时,操作可能会变得更加复杂。我的目标是只有一种实现逻辑的方法。

这是一个示例程序:

int main() {
    Voltage u1 = { 4 };
    Voltage u2 = { 6 };
    Voltage u3 = u1 + u2;
    Voltage u4 = u3 + u2;


    std::cout << "Voltage U1 = " << u1.getVoltage() << " V" << std::endl;
    std::cout << "Voltage U2 = " << u2.getVoltage() << " V" << std::endl;
    std::cout << "Voltage U3 = " << u3.getVoltage() << " V" << std::endl;
    std::cout << "Voltage U4 = " << u4.getVoltage() << " V" << std::endl;
    return 0;
}

我是如何做到这一点的,还是我误会了什么?我是一名 Python 程序员,完全不考虑类型就可以工作^^

我很高兴每一个帮助:) 谢谢。

【问题讨论】:

  • 在基类中实现的operator+ 重载返回一个ElectricalUnit 对象。而已。即使此EletricalUnitVoltage 的子类,此operator+ 重载仍会返回ElectricalUnit。撇开在派生类中使用重载的问题不谈,这就是 C++ 的工作方式,没有办法改变它。
  • 继承对于这项工作来说是一个错误的工具。您可能想研究实现此功能的库,例如boost.units。不幸的是,我可以在这里描述它的复杂性大约是 1e6 倍,而且有很多充分的理由。
  • 我是一名 Python 程序员,完全不考虑类型 -- 你现在已经看到 Python 不是 C++,而且使用 Python(或任何其他语言)C++ 中的技术将无法正常工作。 C++ 是目前最复杂的语言之一,如果你试图在 C++ 中结合其他语言的习语和技术,你将无法快速取得进展。 C++ 是基于值的,而 Python 和其他语言是基于引用的,这一事实已经让你陷入了困境。正确的做法是忘记 Python 的存在,正确学习 C++,并将 C++ 用作 C++。

标签: c++ inheritance operator-overloading subclass


【解决方案1】:

我个人会尝试仅在以下情况下使用第三种方法:

    Voltage operator+ (const Voltage& other) {  // not having this function did not work
        // 1st try:
        return ElectricalUnit::operator+(other); // error: says no conversion is available??

        // 2nd try:
        return (Voltage)ElectricalUnit::operator+(other); // error: also says no conversion is available.

        // 3rd try (read it online)
        ElectricalUnit::operator+(other);
        return *this;  // does give wrong values, because the return value of operator+ is not used
    }

因为第一次尝试返回父类而不是派生类,所以第二个类对我来说有点难以解释,所以我把它留给那个。

中的运算符:

    ElectricalUnit operator+ (const ElectricalUnit& other) const {
        return ElectricalUnit(this->value + other.getValue());
    }

不会改变父类中value的值,所以返回的时候不会有任何值的变化。尝试将代码更改为:

    ElectricalUnit operator+ (const ElectricalUnit& other){
        value += other.getValue();
        return *this;
    }

【讨论】:

  • 在二进制operator+ 中修改this 肯定不是一个好建议,因为运算符通常用于创建一个新对象,它是添加的效果。此外,您示例中的运算符是 const,因此在尝试修改 this 时不会编译。
  • 我已经编辑了帖子。感谢您的建议!
【解决方案2】:

Voltage::operator+ 返回值存在转换问题,因为多态性仅适用于指针和引用。该函数返回一个值,而您正试图返回一个 ElectricalUnit,其中应该是 Voltage

您需要做的是根据ElectricalUnit::operator+ 返回值显式创建一个新的Voltage 实例,如下所示。

Voltage operator+(const Voltage& other)
{
    return Voltage(ElectricalUnit::operator+(other).getValue());
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-05-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-09
    • 2021-07-10
    • 2021-06-07
    • 2011-12-04
    相关资源
    最近更新 更多