我有两个课程,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;
提前感谢您的意见和建议。
丹
答案 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;
}
}