哪个更好:重载operator *或重载强制转换操作符?

时间:2016-03-09 22:00:46

标签: c++ type-conversion operator-overloading

我有两个课程,Permutation和Cycle。循环本质上是一种特殊的排列,但它不是排列的派生类,部分原因如下。两种排列的乘积是另一种排列,而循环的乘积通常不是另一种循环。循环和置换的乘积是一种排列。

对于排列p1,p2和周期c1,c2,我希望以下陈述的预期含义应该清楚:

Permutation p3 = p1*p2;
Permutation p4 = p1*c1;
Permutation p5 = c1*p1; 
Permutation p6 = c1*c2;

我的Cycle和Permutation类的基本结构如下:

class Cycle
{
public:
   // stuff ...     
};

class Permutation
{
public:
    Permutation(const Cycle& cycle);

    friend
    Permutation operator*(const Permutation& left, const Permutation& right);
    // stuff ...
};

我应该/应该如何添加代码(或更改代码)以实现上述用途?

我有一些(可能有缺陷的)想法:

修改Permutation类的第一个想法是这样的:

class Permutation
{
    friend Permutation operator*(const Permutation&, const Cycle&);
    friend Permutation operator*(const Cycle&, const Permutation&);
    friend Permutation operator*(const Cycle&, const Cycle&);

public:
    Permutation(const Cycle& cycle);

    friend
    Permutation operator*(const Permutation& left, const Permutation& right);
    // stuff ...
};

我认为这样可行,但我认为这可能是提供转化运算符的好方法。

这是我的第二个想法:

class Permutation
{

public:
    Permutation(const Cycle& cycle);

    friend
    Permutation operator*(const Permutation& left, const Permutation& right);
    // stuff ...
};

class Cycle
{
public:
    operator Permutation() const
    {
        Permutation p(*this);
        return p;
    }
    // stuff ...     
};

我认为第二个想法应该适用于:

Permutation p4 = p1*c1;

但不是:

Permutation p5 = c1*p1; 
Permutation p6 = c1*c2;

这是第三个想法:

class Permutation
{
    friend Permutation operator*(const Permutation&, const Permutation&);

public:
    Permutation(const Cycle& cycle);

    //friend
    //Permutation operator*(const Permutation& left, const Permutation& right);
    // stuff ...
};

class Cycle
{
public:
    operator Permutation() const
    {
        Permutation p(*this);
        return p;
    }
    // stuff ...     
};

我怀疑这可能适用于

Permutation p4 = p1*c1;
Permutation p5 = c1*p1; 

但我无法想象编译器会知道在赋值中键入转换两个参数:

Permutation p6 = c1*c2;

提前感谢您的意见和建议。

1 个答案:

答案 0 :(得分:0)

我认为你的错误不是从Permutation派生的循环。这是我的建议:

class Permutation
{
public:
    virtual bool IsCycle()
    {
        return false;
    }

    virtual Permutation& operator*(Permutation& right);
};

class Cycle: public Permutation
{
public:
    virtual bool IsCycle()
    {
        return true;
    }

    Permutation& operator*(Permutation& right);
};

Permutation& Permutation::operator*(Permutation& right)
{
    // in this case left operand is NOT a Cycle
    // right operand could be anything

    Permutation& p1 = *this;

    if(right.IsCycle())
    {
        Cycle& c1 = *dynamic_cast<Cycle*>(&right);
        // code for case Permutation p4 = p1*c1;
    }
    else
    {
        Permutation &p2 = right;
        // code for Permutation p3 = p1*p2;
    }
}

Permutation& Cycle::operator*(Permutation& right)
{
    // in this case left operand IS a Cycle
    // right operand could be anything
    Cycle& p1 = *this;
    if(right.IsCycle())
    {
        Cycle& c2 = *dynamic_cast<Cycle*>(&right);
        // code for case Permutation p6 = c1*c2;
    }
    else
    {
        Permutation &p1 = right;
        // code for Permutation p5 = c1*p1; 
    }
}