首页 > 解决方案 > 带有类模板的c ++多态性,没有要调用的匹配函数

问题描述

我正在编写一个可以采用以下之一的类模板,int8_t、int16_t、int32_t、float 和 double。这里是:

#ifndef OPERAND_HPP
# define OPERAND_HPP

# include "IOperand.hpp"
# include <regex>

template <typename T>
class Operand : public IOperand {
private:
    /* Constructors - Destructors */
                            Operand() = default;

    /* Attributes */
    T                       _num;
    eOperandType const      _type;
    std::string const       &_value;

    /* Static functions */
    static int8_t           getValue(Operand<int8_t> const *it) { return it->getNum(); }
    static int16_t          getValue(Operand<int16_t> const *it) { return it->getNum(); }
    static int32_t          getValue(Operand<int32_t> const *it) { return it->getNum(); }
    static float            getValue(Operand<float> const *it) { return it->getNum(); }
    static double           getValue(Operand<double> const *it) { return it->getNum(); }

public:
    /* Constructors - Destructors */
    explicit                Operand(eOperandType t, std::string const &v, T n) : _num(n), _type(t), _value(v) {}
                            Operand(Operand const &rhs) : Operand(rhs.getType(), rhs.toString(), rhs.getNum()) {};
                            ~Operand() override = default;

    /* Operator overloads */
    Operand<T>              &operator=(Operand const &rhs) {
        _num = rhs.getNum();
        _type = rhs.getType();
        _value = rhs.toString();
        return *this;
    }

    IOperand const          *operator+(IOperand const &rhs) const final {

        Operand::getValue(&rhs);

        return &rhs;
    }

    IOperand const          *operator-(IOperand const &rhs) const final { return &rhs; }
    IOperand const          *operator*(IOperand const &rhs) const final { return &rhs; }
    IOperand const          *operator/(IOperand const &rhs) const final { return &rhs; }
    IOperand const          *operator%(IOperand const &rhs) const final { return &rhs; }

    /* ------------------------------------------------- Exceptions ------------------------------------------------- */
    class DivisionByZero : public std::exception {
    public:
        char const          *what() const noexcept final { return "division by zero"; }
    };

    class ModuloByZero : public std::exception {
    public:
        char const          *what() const noexcept final { return "modulo by zero"; }
    };

    class Overflow : public std::exception {
    public:
        char const          *what() const noexcept final { return "overflow"; }
    };

    class Underflow : public std::exception {
    public:
        char const          *what() const noexcept final { return "underflow"; }
    };
    /* -------------------------------------------------------------------------------------------------------------- */

    /* Member functions */
    T                       getNum() const { return _num; }
    int                     getPrecision() const final { return static_cast<int>(_type); }
    eOperandType            getType() const final { return _type; }
    std::string const       &toString() const final { return _value; }
};

#endif /* OPERAND_HPP */

该类继承自以下接口:

#ifndef IOPERAND_HPP
# define IOPERAND_HPP

# include <string>

enum eOperandType {
    INT8,
    INT16,
    INT32,
    FLOAT,
    DOUBLE
};

class IOperand {
public:
    /* Constructors - Destructors */
    virtual                     ~IOperand() = default;

    /* Operator overloads */
    virtual IOperand const      *operator+(IOperand const &) const = 0;
    virtual IOperand const      *operator-(IOperand const &) const = 0;
    virtual IOperand const      *operator*(IOperand const &) const = 0;
    virtual IOperand const      *operator/(IOperand const &) const = 0;
    virtual IOperand const      *operator%(IOperand const &) const = 0;

    /* Member functions */
    virtual int                 getPrecision() const = 0;
    virtual eOperandType        getType() const = 0;
    virtual std::string const   &toString() const = 0;
};

#endif /* IOPERAND_HPP */

我正在努力实现 + 运算符重载。该函数有两个 IOperand & 作为参数,但我需要访问所述参数的 _num 属性。此属性的 getter 不在基类中,仅在派生类中。我尝试了具有以下功能的多态性:

    static int8_t           getValue(Operand<int8_t> const *it) { return it->getNum(); }
    static int16_t          getValue(Operand<int16_t> const *it) { return it->getNum(); }
    static int32_t          getValue(Operand<int32_t> const *it) { return it->getNum(); }
    static float            getValue(Operand<float> const *it) { return it->getNum(); }
    static double           getValue(Operand<double> const *it) { return it->getNum(); }

但是使用 clang++ 编译时出现以下错误消息:

./Operand.tpp:41:15: error: no matching function for call to 'getValue'
        (void)Operand::getValue(&rhs);
./Operand.tpp:19:29: note: candidate function not viable: cannot convert from base class pointer 'const IOperand *' to derived class pointer 'const Operand<int8_t> *'
      (aka 'const Operand<signed char> *') for 1st argument
    static int8_t           getValue(Operand<int8_t> const *it) { return it->getNum(); }

错误消息非常冗长,我知道问题出在哪里。但是我不确定如何解决它,或者是否有更优雅的方法来解决我的问题。我可能可以使用动态强制转换,甚至使用 5 个不同的类而不是模板来摆脱它,但它似乎并不那么好。

谁能指出我正确的方向?

标签: c++ooptemplatespolymorphism

解决方案


推荐阅读