我想创建类似的界面
class Scalar {
public:
Scalar() {}
virtual ~Scalar() {}
//virtual members operators
virtual Scalar& operator+() const = 0;
virtual const Scalar operator-() const;
virtual Scalar& operator=() = 0;
virtual Scalar& operator+=() = 0;
//...
};
我还打算使用一些朋友功能,例如:
friend const Scalar operator+(const Scalar&, const Scalar&);
但是当我派生抽象类并创建派生类时,出现了一个问题,
class RealNumber: public Scalar {
public:
friend const RealNumber operator+(const RealNumber&, const RealNumber&);
//some definitions...
};
根据此逻辑,我需要为从operator+
派生的每个新类定义一个新的Scalar
朋友重载。有什么办法可以解决这个问题,并避免在所有派生类中声明这些朋友?
答案 0 :(得分:3)
我了解您的问题是,您的两个朋友具有完全不同的功能,因为他们具有不同的签名:
friend const Scalar operator+(const Scalar&, const Scalar&);
friend const RealNumber operator+(const RealNumber&, const RealNumber&);
更糟糕的是,选择一个类的外部朋友不会是多态的:将根据编译时类型选择合适的朋友。
首先,您可以考虑重写类本身的运算符(保持签名相同),而不是使用外部重载的朋友。
但这有两个主要挑战:
Scalar
添加RealNumber
怎么办?这将需要实施double dispatch以应对所有可能的组合。 那么,死胡同?
否,还有其他两种选择,具体取决于您的实际问题:
答案 1 :(得分:1)
您可能无法创建虚拟好友函数,但可以创建虚拟运算符(甚至可以$myFriendsData = DB::table('cr_friends as cf')
->where('cf.status', '=', 1)
->join('users as U', function() {})
->whereRaw(
'(
CASE
WHEN cf.friend_to = ' . auth()->user()->id . ' THEN cf.friend_from = U.id
WHEN cf.friend_from = ' . auth()->user()->id . ' THEN cf.friend_to = U.id
END
)'
)
->select('U.*')
->orderBy('U.id', 'desc')
->get();
进行此操作)。
考虑以下代码: 警告:这根本不是很好的设计
operator +
在编写此代码时,我发现可能会引发很多缺陷(例如+运算符实际上是在进行减法运算,如果第二个操作数是BB而不是第一个操作数??会怎样)
因此,关于您的问题,您需要Scalars。因此,您可以执行以下方法:
#include <iostream>
using namespace std;
class AA {
private:
int a;
public:
AA(int a): a(a) {};
inline int getA() const { return a; };
virtual AA operator +(const AA &a) {
AA res(this->getA() + a.getA());
return res;
}
};
class BB: public AA {
public:
BB(int a): AA(a) {}
virtual AA operator +(const AA &a) {
AA res(this->getA() - a.getA());
return res;
}
};
int main() {
BB tmp(1);
AA& a = tmp;
AA b(7);
cout << (a + b).getA();
return 0;
}