指针和引用 + 重载运算符

Pointers and references + overloaded operators

本文关键字:重载 运算符 引用 指针      更新时间:2023-10-16

假设我有一个程序,我想在其中求解方程(像这样(

Number x;
Func fw = x * 4 + x * x;
std::cout << fw(6.0) << "nn";
因此,我

从编写抽象基类开始,在那里我拥有解决这个方程所需的一切。

class Base
{
public:
    Base(){};
    virtual Base* operator*(Base& x) = 0;
    virtual Base* operator*(double x) = 0;
    virtual Base* operator+(Base& x) = 0;
};

和类号

class Number : public Base
{
public:
    virtual Base* operator*(Base& x);
    virtual Base* operator*(double x);
    virtual Base* operator+(Base& x);
};
和带有复制构造函数

的类 Func(或者至少,我认为它是一个复制构造函数(

class Func: public Base
{
    Base * func;
public:
    Func(Base* other)
    {
        func = other;
    }
    Func(Base& other)
    {
        func = &other;
    }
    virtual Base* operator*(Base& x){}
    virtual Base* operator*(double x){}
    virtual Base* operator+(Base&){}
};

所以,我的问题。我的程序适用于x*xx*4,但是当我尝试将它们组合x*x + x*4时,我遇到了问题。

很明显(或者不是(问题是什么。x*x后,我的程序返回指针(Base*(,在我的重载运算符中,我只有(Base&(。因此,程序无法将任何重载运算符与它匹配。

以下是CLion向我展示的内容binary operator + can't be applied to the expression of type Base* and Base*

因此,解决方案可以是再次重载运算符,但使用 argument(Base*(,但我希望有更好的方法来解决这个问题。有吗?

是的,有:编写一个使用值或引用语义而不是指针语义的包装类。例如

class BaseRep // I've renamed your `Base` class
{
public:
    BaseRep(){};
    virtual std::unique_ptr<BaseRep> multiply(const BaseRep& x) = 0;
};
class Base
{
    std::unique_ptr<BaseRep> ptr;
public:
    Base(std::unique_ptr<BaseRep> &&p):ptr(p) {}
    BaseRep& rep() { return *ptr; }
    const BaseRep& rep() const { return *ptr; }
    // and other stuff
};
Base operator*(const Base &x, const Base &y)
{
    return Base( x.rep().multiply(y.rep()) );
}

所有算术运算符都应该返回一个引用(或副本(,绝对不是指针。

template < size_t Index >
struct placeholder {
    template < typename ... Args >
    auto operator()(Args ... args) const
    {
        auto tpl = std::make_tuple(args...);
        return get<Index>(tpl);
    }
 };
 placeholder<0> _1;
 placeholder<1> _2; // etc...
 template < typename T >
 struct val
 {
    T value;
    val(T v) : value(v) {}
    template < typename ... Args >
    auto operator()(Args ... ) const { return value; }
 };
 template < typename LH, typename RH >
 struct plus_operator
 {
     plus_operator(LH l, RH r) : lh(l), rh(r) {}
     LH lh;
     RH rh;
    template < typename ... Args >
    auto operator()(Args ... args) const { return lh(args...) + rh(args...); }
 };
 template < size_t I, typename T >
 auto operator + (placeholder<I> lh, T rh)
 {
     return plus_operator<placeholder<I>,T>{lh,val<T>{rh}};
 }
 template < typename T, size_t I >
 auto operator + (T lh, placeholder<I> rh) ...
 // because this would otherwise be ambiguous...
 template < size_t I1, size_t I2 >
 auto operator + (placeholder<I1> lh, placeholder<I2> rh) ...

与 *、-、/...

 auto fun = _1 * 4 + _1 * _1;
 auto result = fun(5);

未经测试。 无担保。 但这种技术是我相信你想要解决的问题。 它称为"表达式模板"。

哦,你必须覆盖每个可能的运算符是 LH、RH......可能是使用SFINAE的更好方法。